Как использовать псевдоним для реализации метода интерфейса с помощью Mono.Cecil?

Я использую 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, потому что у меня могут быть общие параметры и аргументы в задействованных типах, а простой MethodDefinition не подойдет.

Обновление: в соответствии с рекомендациями Jb Evain, я мигрировал на версию 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);

person Jordão    schedule 13.07.2010    source источник


Ответы (1)


Это одно из неудобств использования версии 0.6. Вы должны поместить только что созданный MethodReference в коллекцию .MemberReferences вашего модуля.

Я настоятельно рекомендую вам перейти на 0.9.

person Jb Evain    schedule 13.07.2010
comment
Большое спасибо, но я тоже пробовал, и это не сработало. - person Jordão; 13.07.2010
comment
Я только что перенес его, и я получаю ту же ошибку. Я обновлю вопрос. - person Jordão; 13.07.2010
comment
Jordão: мне кажется, что это ошибка peverify. Ссылка на метод испускается правильно, но peverify это не нравится. Если я использую ваш точный сценарий, но с методом универсального типа, он работает отлично. Так что мне кажется придется разбираться самому, то есть ставить MethodDefinition, если метод не на generic типе и определен в текущей сборке, либо создашь MethodReference. - person Jb Evain; 14.07.2010
comment
Меня устраивает! Большое спасибо за ответ и за замечательную библиотеку! - person Jordão; 14.07.2010
comment
Знаете ли вы какой-либо программный способ проверки сборки (возможно, в проекте Mono) без использования PEVerify? - person Jordão; 14.07.2010
comment
Круто, рад узнать, что это работает. Что касается программной проверки сборок, кроссплатформенного способа не существует. Все верификаторы обычно сильно привязаны к среде выполнения. Поэтому, если вы согласны с этим, вы, вероятно, можете вызвать неуправляемые методы для этого. Но я никогда не заходил так далеко и всегда прибегал к вызову peverify как для .net, так и для Mono. - person Jb Evain; 14.07.2010