代码之家  ›  专栏  ›  技术社区  ›  zig

在不进行显式类型转换的情况下,将int值动态设置为可为空的枚举属性

  •  1
  • zig  · 技术社区  · 6 年前

    我有一个方法,它将数据表填充为简单的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 (不能为空)一切正常。

    如果我使用显式强制转换,它也可以工作 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框架4.6.2

    2 回复  |  直到 6 年前
        1
  •  3
  •   canton7    6 年前

    这是我能想到的最好的办法。这里有一个明确的检查来查看被分配给的属性是否可以为空,但是我认为您不能避免这种情况。

    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; 如果你需要的话,可以避免。

        2
  •  0
  •   mjwills Myles McDonnell    6 年前

    要考虑的“创造性”选项是:

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

    这看起来很奇怪,但自从 常数 0具有内置 implicit cast 枚举(其他数字没有)。

    所以,将其设置为0,然后将其递增到 实际的 你感兴趣的号码。这里的一个关键好处是,您不会受到使用反射的性能影响(和/或缺乏类型安全性)。 您可能想在代码中添加一条注释,说明您为什么要这样做。;)