Подтвердить что ты не робот

Определить, может ли отображаемое свойство присвоено значение 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, не является вариантом.

4b9b3361

Ответ 1

Вам нужно обрабатывать ссылки null и Nullable<T>, поэтому (в свою очередь):

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

Обратите внимание, что IsByRef - это нечто иное, что позволяет выбирать между int и ref int/out int.

Ответ 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, поскольку объект является классом.