C# 带反射发射的显式运算符

C# 带反射发射的显式运算符,c#,C#,我有一个类需要使用反射发射动态生成。我希望能够显式地将该类的实例强制转换为编译时定义的类型 为了实现这一点,我尝试在使用反射发射定义的类型中重载显式运算符,但在进行强制转换时会抛出错误: System.InvalidCastException:'无法将类型为'MySourceClass'的对象强制转换为类型为'ExplictOperatorTest.MyTargetClass' 这是我使用反射发射定义显式运算符的方式: private static void CreateExplicitOp(T

我有一个类需要使用反射发射动态生成。我希望能够显式地将该类的实例强制转换为编译时定义的类型

为了实现这一点,我尝试在使用反射发射定义的类型中重载显式运算符,但在进行强制转换时会抛出错误:

System.InvalidCastException:'无法将类型为'MySourceClass'的对象强制转换为类型为'ExplictOperatorTest.MyTargetClass'

这是我使用反射发射定义显式运算符的方式:

private static void CreateExplicitOp(TypeBuilder typeBuilder, MethodInfo conversionMethod)
{
    var myType = typeBuilder.AsType();
    var method = typeBuilder.DefineMethod(
        "op_Explicit",
        MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Static,
        typeof(MyTargetClass),
        new Type[] { myType });

    var ilGenerator = method.GetILGenerator();
    var emitRecordLocal = ilGenerator.DeclareLocal(typeof(MyTargetClass));
    ilGenerator.Emit(OpCodes.Nop);
    ilGenerator.Emit(OpCodes.Ldarg_0);
    ilGenerator.EmitCall(OpCodes.Callvirt, conversionMethod, new Type[] { });
    ilGenerator.Emit(OpCodes.Stloc_0);
    ilGenerator.Emit(OpCodes.Ldloc_0);
    ilGenerator.Emit(OpCodes.Ret);
}
这就是我想做的,没有错误:

var mySourceTypeType = CreateMyType();
var mySourceTypeInstance = Activator.CreateInstance(mySourceTypeType);
// System.InvalidCastException: 'Unable to cast object of type 'MySourceClass' to type 'ExplictOperatorTest.MyTargetClass'.'
var myTarget = (MyTargetClass)mySourceTypeInstance;
我将我在IL中的显式声明与从等效的预定义类型生成的声明进行了比较,它看起来基本相同,如果我直接调用
op_explicit
方法,它就会工作

我的问题是:我想做的事情可能吗?如果是的话,我错在哪里

完全复制: 问题在于
mySourceTypeInstance
的编译时类型是
object
,因为这是
Activator.CreateInstance
的返回类型。这意味着你的处境有点像这样:

object obj = new XElement("foo", "text content");
string text = (string) obj; // Throws InvalidCastException
这不会使用
XElement
string
的显式转换,因为转换的可用性是在编译时根据表达式的编译时类型选择的

但是,如果要将绑定决策移动到执行时间,可以使用
dynamic

dynamic obj = new XElement("foo", "text content");
string text = (string) obj; // Works fine
因此,在您的情况下,对于动态生成/实例化的类型,您将使用:

var mySourceTypeType = CreateMyType();
dynamic mySourceTypeInstance = Activator.CreateInstance(mySourceTypeType);
var myTarget = (MyTargetClass)mySourceTypeInstance;
问题是
mySourceTypeInstance
的编译时类型是
object
,因为这是
Activator.CreateInstance
的返回类型。这意味着你的处境有点像这样:

object obj = new XElement("foo", "text content");
string text = (string) obj; // Throws InvalidCastException
这不会使用
XElement
string
的显式转换,因为转换的可用性是在编译时根据表达式的编译时类型选择的

但是,如果要将绑定决策移动到执行时间,可以使用
dynamic

dynamic obj = new XElement("foo", "text content");
string text = (string) obj; // Works fine
因此,在您的情况下,对于动态生成/实例化的类型,您将使用:

var mySourceTypeType = CreateMyType();
dynamic mySourceTypeInstance = Activator.CreateInstance(mySourceTypeType);
var myTarget = (MyTargetClass)mySourceTypeInstance;

问题是
Activator.CreateInstance
返回的是
object
,而不是
MyType
。如果你有(比如说)
objectx=newxelement(“foo”),你会遇到完全相同的问题;字符串y=(字符串)x。您可以使用
dynamic
。。。我希望这能奏效。(基本上,这与你发射的转换操作符无关——这与你最后一行中的演员行为有关。至少从一开始——转换操作符可能也坏了,但你还没有发现。)@Jon Skeet,事实上,如果我使用
dynamic mySourceTypeInstance=Activator.CreateInstance(mySourceTypeType),显式强制转换是有效的取而代之。谢谢。你想让我把我的评论变成一个答案吗?现在还不清楚
dynamic
是否适合您的用例。@Jon Skeet,我很高兴在我的用例中使用dynamic。当然,我只是想理解为什么在完全错误的地方找不到它。所以是的,请这样做,我会接受。问题是
Activator.CreateInstance
返回
object
,而不是
MyType
。如果你有(比如说)
objectx=newxelement(“foo”),你会遇到完全相同的问题;字符串y=(字符串)x。您可以使用
dynamic
。。。我希望这能奏效。(基本上,这与你发射的转换操作符无关——这与你最后一行中的演员行为有关。至少从一开始——转换操作符可能也坏了,但你还没有发现。)@Jon Skeet,事实上,如果我使用
dynamic mySourceTypeInstance=Activator.CreateInstance(mySourceTypeType),显式强制转换是有效的取而代之。谢谢。你想让我把我的评论变成一个答案吗?现在还不清楚
dynamic
是否适合您的用例。@Jon Skeet,我很高兴在我的用例中使用dynamic。当然,我只是想理解为什么在完全错误的地方找不到它。所以,是的,我愿意接受。