views:

87

answers:

3

I wish to automagically discover some information on a provided class to do something akin to form entry. Specifically I am using reflection to return a PropertyInfo value for each property. I can read or write values to each property from my "form", but if the property is defined as "int", I would not be able to, and my program should not even try, to write a null value.

How can I use reflection to determine if a given property can be assigned a null value, without writing a switch statement to check for every possible type? In particular I want to detect the difference between boxed types like "int" vs. "int?", since in the second case I do want to be able to write a null value. The IsValueType and IsByRef don't seem to see a difference.

public class MyClass
{
    // Should tell me I cannot assign a null
    public int Age {get; set;} 
    public DateTime BirthDate {get; set;}
    public MyStateEnum State {get; set;}
    public MyCCStruct CreditCard {get; set;}

    // Should tell me I can assign a null
    public DateTime? DateOfDeath {get; set;}
    public MyFamilyClass Famly {get; set;}
}

Note that I need to determine this information long before I actually attempt to write the value, so using exception handling wrapped around SetValue is not an option.

+3  A: 

From http://msdn.microsoft.com/en-us/library/ms366789.aspx

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))

Type would be your PropertyInfo.PropertyType

Jonas Lincoln
That only returns the nullables, though. Works for DateTime?, but not for MyFamilyClass, as that's not a generic, but still a type that can be assigned a null value
David Hedlund
Yep, that's right.
Jonas Lincoln
+1  A: 
PropertyInfo propertyInfo = ...
bool canAssignNull = 
    !propertyInfo.PropertyType.IsValueType || 
    propertyInfo.PropertyType.IsGenericType &&
        propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)
+8  A: 

You need to handle null references and Nullable<T>, so (in turn):

bool canBeNull = !type.IsValueType || (Nullable.GetUnderlyingType(type) != null);

Note that IsByRef is something different, that allows you to choose between int and ref int / out int.

Marc Gravell
Something I didn't think about but I did test your answer against is arrays, such as int[] (which can be assigned null). Your answer worked correctly for this case as well.
David
Arrays are reference-types, so they work the same as classes.
Marc Gravell