This is really stumping me today. I'm sure its not that hard, but I have a System.Reflection.PropertyInfo object. I want to set its value based on the result of a database lookup (think ORM, mapping a column back to a property).
My problem is if the DB returned value is DBNull, I just want to set the property value to its default, the same as calling:
value = default(T); // where T is the type of the property.
However, the default() method won't compile if you give it a Type, which is what I have:
object myObj = ???; // doesn't really matter. some arbitrary class.
PropertyInfo myPropInf = ???; // the reflection data for a property on the myObj object.
myPropInf.SetValue(myObj, default(myPropInf.PropertyType), null);
The above doesn't compile. default(Type) is invalid. I also thought about doing:
object myObj = ???;
PropertyInfo myPropInf = ???;
myPropInf.SetValue(myObj, Activator.CreateInstance(myPropInf.PropertyType), null);
However, if the Type is string, that would assign the value "new String()", but I really want "null", which is what "default(string)" would return.
So what am I missing here? I suppose a really hacky way would be to create a new instance of myObj's Type and copy the property over, but that just seems stupid...
object myObj = ???;
PropertyInfo myPropInf = ???;
var blank = Activator.CreateInstance(myObj.GetType());
object defaultValue = myPropInf.GetValue(blank, null);
myPropInf.SetValue(myObj, defaultValue, null);
I'd rather not waste the memory to make a whole new instance, just to get the default for the property though. Seems very wasteful.
Any ideas?
Property default values are implementation specific, not type specific. They might coincide in many cases but it doesn't have to be so.
Pass in the BindingFlags parameter to control what GetProperties () looks for. This is an enum flag, so you have to OR the options together. Filter the returned PropertyInfo objects by looking at its properties, such as PropertyInfo.PropertyType.
The following example sets the default value to a private property field. You can assign the default value using the DefaultValueAttribute attribute, as shown below. tutorialsteacher.com is a free self-learning technology web site for beginners and professionals.
The default value of the parameter, or Value if the parameter has no default value. This property is used only in the execution context. In the reflection-only context, use the RawDefaultValue property instead.
I believe if you just do
prop.SetValue(obj,null,null);
If it's a valuetype, it'll set it to the default value, if it's a reference type, it'll set it to null.
object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
The "null" trick will set it to the zero value for the type, which is not necessarily the same as the default for the property. Firstly, if it is a new object, why not just leave it alone? Alternatively, use TypeDescriptor
:
PropertyDescriptor prop = TypeDescriptor.GetProperties(foo)["Bar"];
if (prop.CanResetValue(foo)) prop.ResetValue(foo);
This respects both [DefaultValue]
and the Reset{name}()
patterns (as used by binding and serialization), making it very versatile and re-usable.
If you are doing lots of this, you can also get a performance boost using TypeDescriptor
instead of reflection, by re-using the PropertyDescriptorCollection
and using HyperDescriptor (same code, but much faster than either refletion or raw TypeDescriptor
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With