【发布时间】:2011-05-01 14:57:50
【问题描述】:
我有一些看起来像这样的代码(运行良好):
int integer = 42;
decimal? castTo = integer;
然后我想用反射做一些类似的事情,一些代码看起来像这样:
object value = source; // source was an int originally
var parameters = new object[1];
...
parameters[0] = value;
var setMethod = property.GetSetMethod();
// Call the set method, which takes a decimal? as a parameter
setMethod.Invoke(o, parameters);
当我这样做时,我得到:
failed: System.ArgumentException : Object of type 'System.Int32' cannot be converted to type 'System.Nullable`1[System.Decimal]'.
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
为什么在其他地方可以正常工作的隐式类型转换会因反射而失败?使用反射来执行这种转换有技巧吗?
编辑:感谢大家的回复。这是我根据答案提出的解决方案:
private object Convert(object source, Type destinationType)
{
if (source == null)
{
return null;
}
var sourceType = source.GetType();
// unwrap nullable types
var nullableType = Nullable.GetUnderlyingType(destinationType);
if(nullableType != null)
{
destinationType = nullableType;
}
nullableType = Nullable.GetUnderlyingType(sourceType);
if(nullableType != null)
{
sourceType = nullableType;
}
var implicitCastMethod =
destinationType.GetMethod("op_Implicit",
new[] { sourceType } );
if(implicitCastMethod == null)
{
return null;
}
return implicitCastMethod.Invoke(null, new[] { source });
}
编辑#2:我希望有人提到System.Convert.ChangeType(),它处理这些情况等等。事实证明,op_Implicit 只能转换为限制较少的数字类型。 (当然,因此名称中包含“隐式”)。换句话说,第一个解决方案适用于int → decimal?,但不适用于decimal? → int。 (如果隐式转换失败,如果我希望能够处理从decimal? 回到int 的转换,我似乎需要更改此代码以尝试op_Explicit。)
由于System.Convert.ChangeType() 不适用于Nullable<> 类型,我最终使用了一些类似于我发现的here 的代码(稍作修改):
private static object Convert(object source, Type destinationType)
{
if(destinationType == null)
{
throw new ArgumentNullException("destinationType");
}
if(destinationType.IsGenericType &&
destinationType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (source == null)
{
return null;
}
destinationType = Nullable.GetUnderlyingType(destinationType);
}
return System.Convert.ChangeType(source, destinationType);
}
【问题讨论】:
标签: c# reflection type-conversion