我有一些代码(工作正常)看起来像这样:
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
。 (似乎我需要更改此代码以尝试 op_Explicit
如果隐式转换失败,如果我想能够处理转换 decimal?
回到 int
。)
以来 System.Convert.ChangeType()
不起作用 Nullable<>
类型,我终于使用了一些类似于我发现的代码 这里 (略有修改):
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);
}