Динамически установить значение INT в Nullable enum свойство без явного приведения типа - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть метод, который заполняет DataTable в простой объект DTO.Для упрощения я буду использовать этот пример:

public enum Gender : int
{
    Male = 1,
    Female = 2
}

public class Person
{
    //...
    public Gender? MyGender { get; set; }
}

static void Main(string[] args)
{
    int intValue = 2; // value from DB

    var o = new Person();
    var prop = o.GetType().GetProperty("MyGender");    
    prop.SetValue(o, intValue , null); // <- Exception
}

Вышеуказанные значения:

Объект типа 'System.Int32' нельзя преобразовать в тип 'System.Nullable`1[Test.Program + Gender] '.

Если я объявляю MyGender как Gender (не Nullable), все работает нормально.

Это также работает, если я использую явное приведение prop.SetValue(o, (Gender)intValue, null);

НО, я не хочу ( и не могу ) использовать явное приведение: (Gender)intValue потому что я не знаю базового «жесткого» типа при создании объекта DTO.

Я надеялся на что-то вроде (, доза которого не компилируется ):

var propType = prop.PropertyType;
prop.SetValue(o, (propType)intValue, null);

Я также пытался:

public static dynamic Cast(dynamic obj, Type castTo)
{
    return Convert.ChangeType(obj, castTo);
}    
var propType = prop.PropertyType;
prop.SetValue(o, Cast(intValue, propType), null);

Который бросает:

Неверное приведение из 'System.Int32' к 'System.Nullable`1 [[Test.Program + Gender ...]

Я нахожусь в тупике.какие у меня варианты?

.NET Framework 4.6.2

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

«Творческий» вариант для рассмотрения:

var o = new Person();
o.MyGender = 0;
o.MyGender += intValue;

Это выглядит странно, но работает, так как константа 0 имеет встроенное неявное приведение для перечисления (что не делают другие числа).

Итак, вы устанавливаете его в 0, а затем увеличиваете его до фактического интересующего вас числа. Ключевое преимущество здесьвы не принимаете удар по производительности (и / или отсутствие безопасности типов) при использовании отражения. Возможно, вы захотите добавить комментарий к коду относительно того, почему вы это делаете.;)

0 голосов
/ 11 февраля 2019

Это лучшее, что я могу придумать.Существует явная проверка, чтобы определить, является ли присваиваемое свойство обнуляемым, но я не думаю, что вы можете избежать этого.

public static void Main(string[] args)
{
    int intValue = 2; // value from DB

    var o = new Person();
    var prop = o.GetType().GetProperty("MyGender");   

    // Check whether the property is a nullable. If it is, get the type of underling enum
    // Otherwise, get the type of the enum directly from the property
    var enumType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
    // Convert the int to the enum type
    var convertedValue = Enum.ToObject(enumType, intValue);

    prop.SetValue(o, convertedValue , null);
}

Конечно, плохие вещи могут произойти, если присваиваемое свойство неперечислениеvar convertedValue = enumType.IsEnum ? Enum.ToObject(enumType, intValue); : intValue; этого бы избежать, если бы вам это было нужно.

...