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)"のシグネチャを持たせることができますか?

注:私はMethodInfoを複製し、参照された型のすべてをインポートすることによってMethodDefinitionを返す拡張メソッド( "TypeDefinition.Copy")を持っています。

10

2 答え

基本クラスで、次のメソッドを生成するとしましょう:

public virtual void f(int);

IsVirtual フラグがtrueに設定されていることを確認する必要があります。 IsNewSlot = true というフラグが設定されていることを確認して、仮想メソッドテーブルを参照してください。

さて、オーバーライドされたメソッドの場合、生成する必要があります:

public override void f(int);

これを行うには、メソッドを IsVirtual にするだけでなく、新しい仮想メソッドではなく暗黙的に別のメソッドをオーバーライドするようにメソッドを持たせる必要があるため、 > .IsReuseSlot = true

暗黙のオーバーライドを使用しているので、両方のメソッドが .IsHideBySig = true であることも確認する必要があります。

そのすべてのセットで、適切なオーバーライド方法が必要です。

10
追加された
問題はありません。あなたの問題に対する解決策が見つかりました!
追加された 著者 Jb Evain,
情報をありがとう - 正確に私が必要なもの。何らかの理由で、私はSOまたはMono-Cecilグループから電子メール通知を受け取りませんでした。複数のチャンネルをご利用いただきありがとうございます!
追加された 著者 John Holliday,

他の読者の利益のために、ここに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);
}
7
追加された