我在运行时使用Reflection.Emit创建一个类型.问题是每当我实例化一个新类型的实例时,我必须使用object或dynamic,因为在编译时不知道该类型.除了在分配期间我希望另一种类型隐式地转换为新类型时,这工作正常.该变量愉快地采用新值并且它是相应的类型而不尝试强制转换为其当前类型.
有没有办法创建一个允许隐式转换的新创建类型的变量?我非常乐意放弃编译时检查,但我希望这些演员至少在运行时尝试.
编辑:
这是一个让它更清晰的例子.当您在编译时知道类型时会发生这种情况:
MyClass a;
//this calls the implicit cast operator and 'a' stays of the same type
a = 5;
如果你不这样做会发生这种情况:
Type t = CreateTypeUsingTypeBuilder();
object a = Activator.CreateInstance(t);
//this does not call the implicit cast operator and 'a' just becomes in integer
a = 5;
此外,我对这种行为并不会感到惊讶或者问为什么会这样.我问是否有任何解决方法来实现在运行时检查隐式运算符所需的行为.
最佳答案 为了理解为什么这是不可能的,至少不是直接的,人们需要首先理解隐式转换运算符是如何工作的.
当你写这样的东西
MyNumericType x = new MyNumericType(123);
double y = x;
编译器意识到x和y是不同类型的,并搜索MyNumericType以查看是否定义了隐式转换运算符:
public static implicit operator double(MyNumericType n) {
return n.doubleValue;
}
找到运算符后,编译器会调用它,就像它是常规静态方法一样(which it is).
使用在运行时生成的类型时,也应该在运行时生成转换.例如,如果你这样做
private static Func<object,object> MakeConverter(Type t1, Type t2) {
var p = Expression.Parameter*(typeof(object));
var eFrom = Expression.Convert(p, t1);
var eTo = Expression.Convert(eFrom, t2);
var res = Expression.Convert(eTo, typeof(object));
var lambda = Expression.Lambda<Func<object,object>>(res, new[] { p });
return (Func<object,object>)lambda.Compile();
}
使用此方法,您可以执行以下操作:
Type runtimeType1 = ...
Type runtimeType2 = ...
var converter = MakeConverter(runtimeType1, runtimeType2);
object objRuntimeType1 = ...
object objRuntimeType2 = converter(objRuntimeType1);