我们有一个用int
填充的long?
类型的属性。
当我直接将属性设置为obj.Value = v;
时,这种方法工作得很好,但是当我尝试通过反射info.SetValue(obj, v, null);
来设置属性时,它会给出以下异常:
'System.Int32‘类型的
对象不能转换为'System.Nullable`1System.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
设置属性时不起作用,而直接设置属性时起作用?
发布于 2012-11-07 20:59:39
查看全文:How to set value of a property using Reflection?
如果要为可空类型设置值,请使用完整代码
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);
您需要这样做,因为您不能将任何任意值转换为给定的type...so,您需要像这样转换它
发布于 2012-11-07 21:01:07
当你写的时候:
obj.Value = v;
编译器知道如何为您进行适当的强制转换,并实际编译
obj.Value = new long?((long) v);
当您使用反射时,没有编译器可以帮助您。
发布于 2012-11-07 21:01:43
因为类型long
具有隐式转换方法。
6.1.2 Implicit numeric conversions
您可以将隐式转换方法视为存在于=
符号后面的隐藏方法。
它还适用于可空类型:
int i = 0;
int? j = i; // Implicit conversion
long k = i; // Implicit conversion
long? l = i; // Implicit conversion
但是反过来是行不通的,因为不存在将null
传递给非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.
您不必显式地将int
转换为int?
...或者是long?
。
但是,当您使用反射时,您将绕过隐式转换,并将值直接赋值给属性。这样,您必须显式地转换它。
info.SetValue(obj, (long?)v, null);
反射跳过隐藏在=
后面的所有甜蜜的东西。
https://stackoverflow.com/questions/13270183
复制相似问题