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

Я использую Mono.Cecil для сборки сборки, содержащей производный класс, который переопределяет определенный метод в импортированном базовом классе. Метод переопределения является "неявным" переопределением. Проблема в том, что я не могу понять, как обозначить ее как переопределение.

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

    void CreateMethodOverride(TypeDefinition targetType,
        TypeDefinition baseClass, string methodName, MethodInfo methodInfo)
    {
        // locate the matching base class method, which may
        // reside in a different module
        MethodDefinition baseMethod = baseClass
            .Methods.First(method => method.Name.Equals(methodName));

        MethodDefinition newMethod = targetType.Copy(methodInfo);
        newMethod.Name = baseMethod.Name;
        newMethod.Attributes = baseMethod.Attributes;
        newMethod.ImplAttributes = baseMethod.ImplAttributes;
        newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes;
        targetType.Methods.Add(newMethod);
    }

Я понимаю, что неявное переопределение должно иметь ту же подпись, что и унаследованный метод. Используя приведенный выше код, когда я просматриваю полученный метод в Reflector, базовый класс и методы производного класса имеют одну и ту же подпись, а именно "public virtual void f (int param)".

Я попытался удалить явный "виртуальный" атрибут, но затем производный метод заканчивается как "public void f (int param)".

Как получить полученный метод, чтобы иметь правильную "public override void f (int param)" подпись?

ПРИМЕЧАНИЕ. У меня есть метод расширения ( "TypeDefinition.Copy" ), который клонирует MethodInfo и возвращает MethodDefinition, импортируя все ссылочные типы и т.д.

Ответ 1

В вашем базовом классе скажем, вы создаете следующий метод:

public virtual void f(int);

Вы должны убедиться, что флаг IsVirtual установлен в true. Вы также должны убедиться, что у него есть флаг IsNewSlot = true, чтобы убедиться, что он имеет новый слот в таблице виртуальных методов.

Теперь для переопределенных методов вы хотите сгенерировать:

public override void f(int);

Для этого вам также необходимо иметь метод IsVirtual, но также сказать, что это не новый виртуальный метод, но он неявно переопределяет другой, поэтому вы должны сделать его .IsReuseSlot = true.

И поскольку вы используете неявное переопределение, вы также должны убедиться, что оба метода: .IsHideBySig = true.

С этим всем набором вы должны иметь надлежащий метод переопределения.

Ответ 2

В интересах других читателей, вот окончательный результат, полученный следующим ответом JB:

void CreateMethodOverride(TypeDefinition targetType,
    TypeDefinition baseClass, string methodName, MethodInfo methodInfo)
{
    MethodDefinition baseMethod = baseClass
        .Methods.First(method => method.Name.Equals(methodName));

    MethodDefinition newMethod = targetType.Copy(methodInfo);
    newMethod.Name = baseMethod.Name;

    // Remove the 'NewSlot' attribute
    newMethod.Attributes = baseMethod.Attributes & ~MethodAttributes.NewSlot;

    // Add the 'ReuseSlot' attribute
    newMethod.Attributes |= MethodAttributes.ReuseSlot;

    newMethod.ImplAttributes = baseMethod.ImplAttributes;
    newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes;
    targetType.Methods.Add(newMethod);
}