C# 确定反射属性是否可以指定为null
我希望自动发现所提供类的一些信息,以便执行类似于表单条目的操作。具体来说,我使用反射为每个属性返回PropertyInfo值。我可以从我的“表单”中读取或写入每个属性的值,但是如果属性被定义为“int”,我将无法,我的程序甚至不应该尝试写入空值 如何使用反射来确定是否可以为给定属性分配空值,而不必编写switch语句来检查每种可能的类型?我特别想检测装箱类型之间的差异,比如“int”和“int?”,因为在第二种情况下,我确实希望能够写入空值。IsValueType和IsByRef似乎没有区别C# 确定反射属性是否可以指定为null,c#,.net,reflection,C#,.net,Reflection,我希望自动发现所提供类的一些信息,以便执行类似于表单条目的操作。具体来说,我使用反射为每个属性返回PropertyInfo值。我可以从我的“表单”中读取或写入每个属性的值,但是如果属性被定义为“int”,我将无法,我的程序甚至不应该尝试写入空值 如何使用反射来确定是否可以为给定属性分配空值,而不必编写switch语句来检查每种可能的类型?我特别想检测装箱类型之间的差异,比如“int”和“int?”,因为在第二种情况下,我确实希望能够写入空值。IsValueType和IsByRef似乎没有区别 p
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的异常处理不是一个选项。From
if(type.IsGenericType&&type.GetGenericTypeDefinition()==typeof(可空))
Type
将是您的PropertyInfo.PropertyType
PropertyInfo-PropertyInfo=。。。
PropertyInfo propertyInfo = ...
bool canAssignNull =
!propertyInfo.PropertyType.IsValueType ||
propertyInfo.PropertyType.IsGenericType &&
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)
布尔卡纳西零=
!propertyInfo.PropertyType.IsValueType | |
propertyInfo.PropertyType.IsGenericType&&
propertyInfo.PropertyType.GetGenericTypeDefinition()==typeof(可为空)
您需要处理null
引用和null
,因此(依次):
请注意,
IsByRef
有所不同,它允许您在int
和ref int
/out int
之间进行选择,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,则它将返回null。所以没有理由在这里检查。除非是为了树立榜样。
public U Assignment Valuer默认值(对象项)
{
如果(项==null)
{
Type Type=typeof(U);//来自泛型参数的类型
//int、bool、struct等基本类型不能为null
//除了int?,bool?,Nullable。。。
bool notNullable=type.IsValueType||
(type.IsGenericType&&type.GetGenericTypeDefinition()!=typeof(可空));
如果(不可为空)
返回默认值(T);
}
退货(U)项;
}
注意:大多数情况下,您可以检查变量是否为null。然后使用默认值(T)。默认情况下,如果对象是一个类,它将返回null。但它只返回可为null的值。适用于DateTime?,但不适用于MyFamilyClass,因为这不是泛型,但仍然是一种可以分配空值的类型结合Marc的答案,这有助于mestring可以为空,但不可为空。我没有想到这一点,但我确实针对is数组测试了您的答案,例如int[](可以分配空值)。你的答案在这种情况下也适用。数组是引用类型,因此它们与类的工作方式相同。我认为应该注意的是,在OP中,有使用int的示例?和DateTime?,因此第一次检查将返回true(!type.IsValueType)。与MSDN中给出的方法相比,我更喜欢这种方法,但我很好奇为什么您添加了一个似乎是多余的检查。也许,因为你想处理所有超出要求的情况?@pqsk,因为问题是“…可以分配为空”;需要考虑参考types@MarcGravell这只是巧合,我没有跟踪你。我无法访问
IsValueType
,但我确实在调试器中找到了它。我必须使用强制转换吗?使用PropertyInfo比直接使用类型有更多的开销。但是,如果您需要其他功能,可能会有所帮助。
bool canBeNull = !type.IsValueType || (Nullable.GetUnderlyingType(type) != 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;
}