代码之家  ›  专栏  ›  技术社区  ›  steve16351

带反射发射的显式运算符

c#
  •  0
  • steve16351  · 技术社区  · 6 年前

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

    为了实现这一点,我尝试在使用reflection emit定义的类型中重载显式运算符,但是当涉及到强制转换时,它会抛出错误:

    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;
    

    op_Explicit 方法,然后它就工作了。

    完全复制: https://dotnetfiddle.net/1AgRuJ

    1 回复  |  直到 6 年前
        1
  •  3
  •   Jon Skeet    6 年前

    问题是 编译时间 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;