通过反射设置属性时,类型转换问题(Type conversion issue when settin

2019-07-03 15:29发布

我们有类型的属性long? 这被充满int

当我刚刚设置的属性直接能正常工作obj.Value = v; 但是当我尝试,并设置通过反射属性info.SetValue(obj, v, null); 它给了我以下异常:

类型“System.Int32”的对象不能被转换为类型“System.Nullable`1 [System.Int64]”。

这是一个简单的场景:

    class TestClass
    {
        public long? Value { get; set; }
    }

    [TestMethod]
    public void TestMethod2()
    {
        TestClass obj = new TestClass();
        Type t = obj.GetType();

        PropertyInfo info = t.GetProperty("Value");
        int v = 1;

        // This works
        obj.Value = v;

        // This does not work
        info.SetValue(obj, v, null);
    }

它为何不通过设置该属性时,工作reflection而它直接设置属性时?

Answer 1:

查看全文: 如何设置使用反射属性的值?

完整的代码,如果你正在为可空类型值

public static void SetValue(object inputObject, string propertyName, object propertyVal)
{
    //find out the type
    Type type = inputObject.GetType();

    //get the property information based on the type
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propertyName);

    //find the property type
    Type propertyType = propertyInfo.PropertyType;

    //Convert.ChangeType does not handle conversion to nullable types
    //if the property type is nullable, we need to get the underlying type of the property
    var targetType = IsNullableType(propertyType) ? Nullable.GetUnderlyingType(propertyType) : propertyType;

    //Returns an System.Object with the specified System.Type and whose value is
    //equivalent to the specified object.
    propertyVal = Convert.ChangeType(propertyVal, targetType);

    //Set the value of the property
    propertyInfo.SetValue(inputObject, propertyVal, null);

}
private static bool IsNullableType(Type type)
{
    return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
}

你需要的值转换这样即需要值转换为你的财产类型一样,如下

PropertyInfo info = t.GetProperty("Value");
object value = null;
try 
{ 
    value = System.Convert.ChangeType(123, 
        Nullable.GetUnderlyingType(info.PropertyType));
} 
catch (InvalidCastException)
{
    return;
}
propertyInfo.SetValue(obj, value, null);

你需要这样做,因为你不能任何arbirtary值转换为给定类型...所以你需要将它转换这样的



Answer 2:

当你写:

obj.Value = v;

编译器知道如何做正确的铸造为您和实际上编译

obj.Value = new long?((long) v);

当您使用反射没有编译器来帮助你。



Answer 3:

因为类型long有一个隐式转换方法。

6.1.2隐式数值转换

你可以看到隐式转换方法存在的背后隐藏方法=符号。

它也可空类型的工作:

int i = 0;
int? j = i; // Implicit conversion
long k = i; // Implicit conversion
long? l = i; // Implicit conversion

但周围走另一条路行不通,因为没有隐式转换存在一个传递null到非空:

int? i = 0;
int j = i; // Compile assert. An explicit conversion exit... 
int k = (int)i; // Compile, but if i is null, you will assert at runtime.

你不必为显式转换intint? ...或long?

但是,当您使用反射,你绕过隐式转换,直接分配价值的财产。 这样一来,你必须把它明确地转换。

info.SetValue(obj, (long?)v, null);

反射跳过所有甜的东西背后隐藏的=



Answer 4:

巩固和扩大Pranay蛙的回答来处理enum S按所建议SilverNinja (并回答thecoop ),并把在一个地方积累的学习收获。 这是一个多一点的副本/ pastable;

private void SetApiSettingValue(object source, string propertyName, object valueToSet)
{
    // find out the type
    Type type = source.GetType();

    // get the property information based on the type
    System.Reflection.PropertyInfo property = type.GetProperty(propertyName);

    // Convert.ChangeType does not handle conversion to nullable types
    // if the property type is nullable, we need to get the underlying type of the property
    Type propertyType = property.PropertyType;
    var targetType = IsNullableType(propertyType) ? Nullable.GetUnderlyingType(propertyType) : propertyType;

    // special case for enums
    if (targetType.IsEnum)
    {
        // we could be going from an int -> enum so specifically let
        // the Enum object take care of this conversion
        if (valueToSet != null)
        {
            valueToSet = Enum.ToObject(targetType, valueToSet);
        }
    }
    else
    {
        // returns an System.Object with the specified System.Type and whose value is
        // equivalent to the specified object.
        valueToSet = Convert.ChangeType(valueToSet, targetType);
    }

    // set the value of the property
    property.SetValue(source, valueToSet, null);
}

private bool IsNullableType(Type type)
{
    return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
}


Answer 5:

反射性地创建新的对象时,我也遇到了这个问题。

这是多么不这样做:

  var newOne = Activator.CreateInstance(srcProp.GetType());

  srcProp.SetValue(newGameData, newOne, null);

这是如何做到这一点:

  var newOne = Activator.CreateInstance(srcProp.PropertyType);

  srcProp.SetValue(newGameData, newOne, null);


文章来源: Type conversion issue when setting property through reflection
标签: c# reflection