views:

1676

answers:

3

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?

+6  A: 
object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
Darin Dimitrov
thanks for the info. Could you shed any light on my question? I've referenced and linked to your comment. cheers. My question is question ID: 1046928/working-with-an-unknown-number-of-unknown-types-net
andy
Since there is no TypeDescriptor in Silverlight, this is the only SL way to do this (that I know of).
Peter Oehlert
I think this would blow up if the type is "System.Void", you have to check for that: object defaultValue = type.IsValueType
Patrik Hägne
+3  A: 

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.

BFree
wow, that does work! learn something every day :) Thanks!
rally25rs
That sets it to the zero value for the type, not the property's default. See my answer for more.
Marc Gravell
+4  A: 

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).

Marc Gravell