代码之家  ›  专栏  ›  技术社区  ›  Jordão

如何将接口方法实现与mono.cecil别名?

  •  1
  • Jordão  · 技术社区  · 14 年前

    我在用 Mono.Cecil (0.6.9.0版)对实现接口方法的方法进行别名。为此,我必须添加一个 Override 指向指向接口方法的目标方法(与vb.net非常类似),如下所示:

    using System;
    using System.Reflection;
    using Mono.Cecil;
    
    class Program {
    
      static void Main(string[] args) {
        var asm = AssemblyFactory.GetAssembly(Assembly.GetExecutingAssembly().Location);
    
        var source = asm.MainModule.Types["A"];
        var sourceMethod = source.Methods[0];
        var sourceRef = new MethodReference(
          sourceMethod.Name,
          sourceMethod.DeclaringType,
          sourceMethod.ReturnType.ReturnType,
          sourceMethod.HasThis,
          sourceMethod.ExplicitThis,
          sourceMethod.CallingConvention);
    
        var target = asm.MainModule.Types["C"];
        var targetMethod = target.Methods[0];
        targetMethod.Name = "AliasedMethod";
        targetMethod.Overrides.Add(sourceRef);
    
        AssemblyAssert.Verify(asm); // this will just run PEVerify on the changed assembly
      }
    
    }
    
    interface A {
      void Method();
    }
    
    class C : A {
      public void Method() { }
    }
    

    我得到的是 PEVerify.exe 指示类不再实现接口方法的错误。似乎在更改的程序集中,重写引用和接口中的方法之间存在令牌不匹配:

    [MD]: Error: Class implements interface but not method (class:0x02000004; interface:0x02000002; method:0x06000001). [token:0x09000001]
    

    我知道如果我使用 MethodDefinition 直接起作用:

    targetMethod.Overrides.Add(sourceMethod);
    

    但我真的需要用 MethodReference 因为我可能在涉及的类型中有泛型参数和参数,并且 方法定义 不行。

    更新 :根据建议 Jb Evain 我已经 migrated 到0.9.3.0版。但是,同样的错误仍然会发生。迁移的代码如下:

    var module = ModuleDefinition.ReadModule(Assembly.GetExecutingAssembly().Location);
    
    var source = module.GetType("A");
    var sourceMethod = source.Methods[0];
    
    var sourceRef = new MethodReference(
      sourceMethod.Name,
      sourceMethod.ReturnType) {
        DeclaringType = sourceMethod.DeclaringType,
        HasThis = sourceMethod.HasThis,
        ExplicitThis = sourceMethod.ExplicitThis,
        CallingConvention = sourceMethod.CallingConvention 
    };
    
    var target = module.GetType("C");
    var targetMethod = target.Methods[0];
    targetMethod.Name = "AliasedMethod";
    targetMethod.Overrides.Add(sourceRef);
    
    1 回复  |  直到 14 年前
        1
  •  3
  •   Jb Evain    14 年前

    这是使用0.6的麻烦之一。必须将新创建的方法引用放入模块的.MemberReferences集合中。

    我强烈建议你换到0.9。