Passing properties as parameters to be Got and Set

2019-09-02 17:06发布

Well, I need to repeat same code for many properties. I've seen examples taking Action delegates, but they don't fit quite well here.

I want something like this: (see explanation below)

Dictionary<Property, object> PropertyCorrectValues;
public bool CheckValue(Property P) { return P.Value == PropertyCorrectValues[P]; }
public void DoCorrection(Property P) { P.Value = PropertyCorrectValues[P]; }    

.

I want to have a dictionary containing many properties and their respective "correct" values. (I know it's not well declared, but that's the idea). Properties are not necessarely inside my class, some of them are in objects of different assemblies.

A method bool CheckValue(Property). This method must access the actual value of the property and compare to the correct value.

And a method a void DoCorrection(Property). This one sets the property value to the correct value.

Remember I have many of those properties, I wouldn't like to call the methods by hand for each property. I'd rather iterate through the dicionary in a foreach statement.


So, the main question is in the title.

  • I've tried the by ref, but properties don't accept that.

  • Am I obligated to use reflection??? Or is there another option (if I need, reflection answer will be accepted as well).

  • Is there anyway I can make a dictionary with pointers in C#? Or some kind of assignment that changes the value of variable's target instead of changing the target to another value?

Thanks for the help.

2条回答
我想做一个坏孩纸
2楼-- · 2019-09-02 17:29

In addition to Ben's code I'd like to contribute the following code fragment:

Dictionary<string,object> PropertyCorrectValues = new Dictionary<string,object>();

PropertyCorrectValues["UserName"] = "Pete"; // propertyName
PropertyCorrectValues["SomeClass.AccountData"] = "XYZ"; // className.propertyName

public void CheckAndCorrectProperties(object obj) {
    if (obj == null) { return; }
    // find all properties for given object that need to be checked
    var checkableProps = from props 
            in obj.GetType().GetProperties()
            from corr in PropertyCorrectValues
            where (corr.Key.Contains(".") == false && props.Name == corr.Key) // propertyName
               || (corr.Key.Contains(".") == true && corr.Key.StartsWith(props.DeclaringType.Name + ".") && corr.Key.EndsWith("." + props.Name)) // className.propertyName
            select new { Property = props, Key = corr.Key };
    foreach (var pInfo in checkableProps) {
        object propValue = pInfo.Property.GetValue(obj, null);
        object expectedValue = PropertyCorrectValues[pInfo.Key];
        // checking for equal value
        if (((propValue == null) && (expectedValue != null)) || (propValue.Equals(expectedValue) == false)) {
            // setting value
            pInfo.Property.SetValue(obj, expectedValue, null);
        }
    }
}

When using this "automatic" value correction you might also consider:

  • You cannot create a PropertyInfo object just by knowing the property name and independently of the declaring class; that's why I chose string for the key.
  • When using the same property name in different classes then you might need to change the code that is doing the actual assignment because the type between the correct value and the property type might differ.
  • Using the same property name in different classes will always perform the same check (see point above), so you might need a syntax for property names to restrict it to a specific class (simple dot notation, doesn't work for namespaces or inner classes, but might be extended to do so)
  • If needed you can replace the "check" and "assign" part with separate method calls, but it might be done inside the code block as stated in my example code.
查看更多
ら.Afraid
3楼-- · 2019-09-02 17:36

You can do this using reflection. Get a list of the properties on the object of interest with typeof(Foo).GetProperties(). Your PropertyCorrectValues property can have type IDictionary<PropertyInfo, object>. Then use the GetValue and SetValue methods on PropertyInfo to perform the desired operations:

public bool CheckProperty(object myObjectToBeChecked, PropertyInfo p) 
{ 
    return p.GetValue(myObjectToBeChecked, null).Equals(PropertyCorrectValues[p]); 
}
public void DoCorrection(object myObjectToBeCorrected, PropertyInfo p) 
{ 
    p.SetValue(myObjectToBeCorrected, PropertyCorrectValues[p]); 
}
查看更多
登录 后发表回答