确定是否可以将反射属性指定为null

时间:2009-11-20 12:31:57

标签: c# .net reflection

我希望自动发现有关提供的类的一些信息,以执行类似于表单输入的操作。具体来说,我使用反射为每个属性返回PropertyInfo值。我可以从我的“表单”中读取或写入每个属性的值,但如果属性被定义为“int”,我将无法编写空值,我的程序甚至不能尝试写入空值。

如何使用反射来确定是否可以为给定属性分配空值,而无需编写switch语句来检查每种可能的类型?特别是我想检测盒装类型之间的区别,如“int”与“int?”,因为在第二种情况下,我希望能够写入空值。 IsValueType和IsByRef似乎没有区别。

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;}
}

请注意,我需要在实际尝试写入值之前确定此信息,因此使用围绕SetValue的异常处理不是一种选择。

4 个答案:

答案 0 :(得分:72)

您需要处理null个引用和Nullable<T>,所以(依次):

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

请注意IsByRef有所不同,允许您在intref int / out int之间进行选择。

答案 1 :(得分:9)

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

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

Type将是您的PropertyInfo.PropertyType

答案 2 :(得分:4)

PropertyInfo propertyInfo = ...
bool canAssignNull = 
    !propertyInfo.PropertyType.IsValueType || 
    propertyInfo.PropertyType.IsGenericType &&
        propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)

答案 3 :(得分:0)

Marc和Jonas都有部分来确定是否可以为泛型类型指定null。

// A silly example. default(T) will return null if it is nullable. So no reason to check here. Except for the sake of having an example.
public U AssignValueOrDefault<U>(object item)
{
    if (item == null)
    {
        Type type = typeof(U); // Type from Generic Parameter

        // Basic Types like int, bool, struct, ... can't be null
        //   Except int?, bool?, Nullable<int>, ...
        bool notNullable = type.IsValueType ||
                           (type.IsGenericType && type.GetGenericTypeDefinition() != typeof(Nullable<>)));

        if (notNullable)
            return default(T);
    }

    return (U)item;
}

注意:大多数情况下,您可以检查变量是否为空。然后使用默认值(T)。它默认返回null,对象是一个类。