public class Test
{
public long? LongValue { get; set; }
}
//----------
var propInfo = typeof(Test).GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(p => p.Name == "LongValue");
//propInfo of Test.LongValue property
if (propInfo != null)
{
int intValue = 99;
var testObj = new Test();
testObj.LongValue = intValue; //This line succeeds
propInfo.SetValue(testObj, intValue); //This throws System.ArgumentException
}
propInfo。当直接赋值成功时,SetValue抛出以下异常:
类型为"System"的未处理异常。ArgumentException'发生在mscorlib.dll
附加信息:System类型的对象。Int32'不能转换为类型'System.Nullable ' 1[System.Int64]'.
这是正确的行为。
直接赋值与基于反射的setter调用之间的区别在于,在直接赋值中,编译器知道被赋值的属性的类型,并为您插入适当的转换。换句话说,当你写
testObj.LongValue = intValue;
编译器解释它的方式就像你写
一样testObj.LongValue = (long)intValue;
因为它知道LongValue
的类型是long
。
Reflection是一个相当低级的API,因此它不会为您插入不必要的转换*,因此您需要在代码中添加强制类型转换。
*由于值类型的所有参数在通过反射调用期间都经过装箱和拆箱,因此碰巧是装箱类型的转换将成功。例如,传递long
来代替Nullable<long>
参数是有效的,因为该值经过装箱转换。
您需要在设置值之前将其转换为类型。
long? temp = intValue;
propInfo.SetValue(testObj, temp);