简体   繁体   中英

How to alias an interface method implementation with Mono.Cecil?

I'm using Mono.Cecil (version 0.6.9.0) to alias a method that implements an interface method. To do that, I have to add an Override to the target method that points back to the interface method (much like what's possible with VB.NET), like this:

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() { }
}

What I'm getting is a PEVerify.exe error that indicates that my class doesn't implement the interface method anymore. It seems that there's a token mismatch in the changed assembly between the override reference and the method in the interface:

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

I know that if I use the MethodDefinition directly it will work:

targetMethod.Overrides.Add(sourceMethod);

But I really need to use a MethodReference because I might have generic parameters and arguments in the types involved, and a simple MethodDefinition won't do.

: As recommended by Jb Evain , I've migrated to version 0.9.3.0. :按照Jb Evain的建议,我已经迁移到0.9.3.0版。 But, the same error still happens. Here's the migrated code:

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);

That's one of the annoyance of using the 0.6. You have to put the newly created MethodReference in the .MemberReferences collection of your module.

I strongly suggest you switch to 0.9.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM