Определить, может ли отображаемое свойство присвоено значение null
Я хочу автоматически обнаружить некоторую информацию о предоставленном классе, чтобы сделать что-то похожее на запись. В частности, я использую отражение для возврата значения 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, не является вариантом.
Ответы
Ответ 1
Вам нужно обрабатывать ссылки null
и Nullable<T>
, поэтому (в свою очередь):
bool canBeNull = !type.IsValueType || (Nullable.GetUnderlyingType(type) != null);
Обратите внимание, что IsByRef
- это нечто иное, что позволяет выбирать между int
и ref int
/out int
.
Ответ 2
От http://msdn.microsoft.com/en-us/library/ms366789.aspx
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
Type
будет вашим PropertyInfo.PropertyType
Ответ 3
PropertyInfo propertyInfo = ...
bool canAssignNull =
!propertyInfo.PropertyType.IsValueType ||
propertyInfo.PropertyType.IsGenericType &&
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)
Ответ 4
У Марка и Джонаса есть части, чтобы определить, может ли общий тип присваиваться 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, поскольку объект является классом.