How do we use PropertyInfo when we don't know data type?
-
I wrote a class that binds a specific property of a control to Properties in another class. For example, given the class below:
public class MyClass { public int MyProperty { get { //do something and return integer } { set { //do something and set an integer } }
I can bind the SelectedIndex property of a ComboBox toMyClass.MyProperty
It all worked great until I run into properties that return enumerated types. I looked at the IL code of my classes and the enumerated types are int32 so when I call the PropertyInfo.SetValue method with the value casted to int32 my program still crashes. The error I get is System.ArgumentException "Object type cannot be converted to target type". I did try using Whidbey and it works, but I can't wait until it gets released. Following is my code:private void SetPropertyValue(object obj, string propertyName, string val) { Type objectType = obj.GetType(); PropertyInfo propInfo = objectType.GetProperty(propertyName); string dataType = propInfo.PropertyType.FullName; if (dataType == "System.Integer" || dataType == "System.Int32") { propInfo.SetValue(obj, Convert.ToInt32(val), null); } else if (dataType == "System.Decimal") { propInfo.SetValue(obj, Convert.ToDecimal(val), null); } else if (dataType == "System.String") { propInfo.SetValue(obj, val, null); } else { Int32 val2 = Convert.ToInt32(val); propInfo.SetValue(obj, val2, null); //<--- crashes right here "System.ArgumentException" // "Object type can not be converted to target type" } }
-
I wrote a class that binds a specific property of a control to Properties in another class. For example, given the class below:
public class MyClass { public int MyProperty { get { //do something and return integer } { set { //do something and set an integer } }
I can bind the SelectedIndex property of a ComboBox toMyClass.MyProperty
It all worked great until I run into properties that return enumerated types. I looked at the IL code of my classes and the enumerated types are int32 so when I call the PropertyInfo.SetValue method with the value casted to int32 my program still crashes. The error I get is System.ArgumentException "Object type cannot be converted to target type". I did try using Whidbey and it works, but I can't wait until it gets released. Following is my code:private void SetPropertyValue(object obj, string propertyName, string val) { Type objectType = obj.GetType(); PropertyInfo propInfo = objectType.GetProperty(propertyName); string dataType = propInfo.PropertyType.FullName; if (dataType == "System.Integer" || dataType == "System.Int32") { propInfo.SetValue(obj, Convert.ToInt32(val), null); } else if (dataType == "System.Decimal") { propInfo.SetValue(obj, Convert.ToDecimal(val), null); } else if (dataType == "System.String") { propInfo.SetValue(obj, val, null); } else { Int32 val2 = Convert.ToInt32(val); propInfo.SetValue(obj, val2, null); //<--- crashes right here "System.ArgumentException" // "Object type can not be converted to target type" } }
You can't set a property whose type is enum to an int. You have to convert it to an enum type. The best way to do this is to get the type of the property you are SETTING, using PropertyInfo.PropertyType. Then, using that type, get the TypeConverter from the TypeDescriptor.GetConverter. Test for "CanConvertTo", and if successful, to a ConvertTo and pass the resulting object to the SetValue method. Marc MyXaml Advanced Unit Testing YAPO
-
You can't set a property whose type is enum to an int. You have to convert it to an enum type. The best way to do this is to get the type of the property you are SETTING, using PropertyInfo.PropertyType. Then, using that type, get the TypeConverter from the TypeDescriptor.GetConverter. Test for "CanConvertTo", and if successful, to a ConvertTo and pass the resulting object to the SetValue method. Marc MyXaml Advanced Unit Testing YAPO
Marc, Thanks a lot for your help. :) I couldn't do a conversion from integer, but interestingly enough I was able to convert from string and the problem got solved. The code below has the fix.
else if (propInfo.PropertyType.IsEnum) { TypeConverter tc = TypeDescriptor.GetConverter(propInfo.PropertyType); if (tc.CanConvertFrom(Type.GetType("System.String"))) { object valToSet = tc.ConvertFromString(val); propInfo.SetValue(obj, valToSet, null); } else throw new Exception and figure out next problem }
-
Marc, Thanks a lot for your help. :) I couldn't do a conversion from integer, but interestingly enough I was able to convert from string and the problem got solved. The code below has the fix.
else if (propInfo.PropertyType.IsEnum) { TypeConverter tc = TypeDescriptor.GetConverter(propInfo.PropertyType); if (tc.CanConvertFrom(Type.GetType("System.String"))) { object valToSet = tc.ConvertFromString(val); propInfo.SetValue(obj, valToSet, null); } else throw new Exception and figure out next problem }
rudy.net wrote: I couldn't do a conversion from integer If the "number" is a string, like "5", then it should still do the conversion to the enum type. At least, so it says in the docs for Enum.Parse, which the type converter should be using. In general, you should be able to convert any value type to a string, and then be able to convert it to the appropriate property type. Otherwise, things like MyXaml wouldn't work. :) Marc MyXaml Advanced Unit Testing YAPO