Dav*_*rab 11 c# operators implicit-conversion explicit-conversion
我想使用反射,并使用反射进行隐式或显式转换.
鉴于我已经用这种方式定义了Foo
public class Foo
{
public static explicit operator decimal(Foo foo)
{
return foo.Value;
}
public static explicit operator Foo(decimal number)
{
return new Foo(number);
}
public Foo() { }
public Foo(decimal number)
{
Value = number;
}
public decimal Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时
decimal someNumber = 42.42m;
var test = (Foo)someNumber;
Console.WriteLine(test); // Writes 42.42 No problems
Run Code Online (Sandbox Code Playgroud)
当我尝试使用Foo定义一个类作为成员类型并使用反射来设置它时.我得到以下例外.
Error : Object of type 'System.Decimal' cannot be converted to type 'Foo'.
StackTrace: at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
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.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
Run Code Online (Sandbox Code Playgroud)
这是我用于使用反射设置属性的代码
public class FooComposite
{
public Foo Bar { get; set; }
}
var properties = typeof(FooComposite).GetProperties();
var testFoo = new FooComposite();
foreach(var propertyInfo in properties)
{
propertyInfo.SetValue(testFoo, 17.17m, null); // Exception generated on this line
}
Console.WriteLine(testFoo.Bar); // Never gets here
Run Code Online (Sandbox Code Playgroud)
我该怎么做这个转换?
那么它与你的非反射代码没有什么不同,你仍然需要明确地将数字转换为Foo:
propertyInfo.SetValue(testFoo,(Foo)17.17m, null);
Run Code Online (Sandbox Code Playgroud)
实例:http://rextester.com/rundotnet?code = BPQ74480
出于兴趣,我尝试了一些替代方案.
我需要像 Ted H 这样的功能,但我是这样实现的:
var cast = typeof(dest).GetMethod("op_Explicit", new Type[] { typeof(source) });
var result = cast.Invoke(null, new object[] {value});
Run Code Online (Sandbox Code Playgroud)
编辑:我最近需要一个更进化的版本,这就是我想出的。请注意,它并未涵盖所有可用的转换。
private static object DynamicCast(object source, Type destType) {
Type srcType = source.GetType();
if (srcType == destType) return source;
var paramTypes = new Type[] { srcType };
MethodInfo cast = destType.GetMethod("op_Implicit", paramTypes);
if (cast == null) {
cast = destType.GetMethod("op_Explicit", paramTypes);
}
if (cast != null) return cast.Invoke(null, new object[] { source });
if (destType.IsEnum) return Enum.ToObject(destType, source);
throw new InvalidCastException();
}
Run Code Online (Sandbox Code Playgroud)