2

を使用して実行時に型を構築していますReflection.Emit。エンド ユーザーは、基本型と、新しい型がサポートするインターフェイスを提供します。基本型がサポートできないメンバーがインターフェイスに含まれている場合は、静的フィールドに格納されているデリゲートを呼び出すスタブ メソッドを作成します (15 個以下のパラメーターを持つ非ジェネリック メソッドのみをサポートし、ref パラメーターまたは out パラメーターを使用しないのが現在のパラメーターです)。要件. この制限で問題を持ち出さないでください. デリゲートは baseType の最初のパラメータを受け取ります.これは, ユーザーが型を構築しようとする前に与えることができます.

ただし、型によって満たされるインターフェイス メンバーのデリゲート スタブを作成することは避けたいと思います。例えば

public class Goose
{
     public void Quack()
     {
       // quack implementation details go here.
     }
}

public interface IDuck
{
     void Quack()
}

ここで私のビルダーに送っていただければ、グースがインターフェイスを満たしているため、 のスタブを作成しGooseません。new[]{typeof(IDuck)}void Quack()

Goose は IDuck を実装していないため、インターフェイス マッピングはTypeBuilder機能しません。構築する必要がある型ではサポートされていないため、新しく構築された型にインターフェイス マッピングを要求することはできません。

リモートで効率的な方法でこれを解決するにはどうすればよいですか? 一般に公開されているメンバーのみを調査する必要があり、型が同じメソッドを持つインターフェイスを明示的に実装している場合、それをターゲットとして使用すべきではないと想定できます。(例えば、Goose が実装されている場合void IGoose.Quack()、それは のターゲットと見なされるべきではありませんvoid IDuck.Quack())。(とにかく、 BindingFlags.Public | BindingFlags.Instanceこれらの要素を除外するには十分なはずです)。

4

2 に答える 2

0

ハッシュセットへのリフレクションを介して、すべての基本型 public 実装メンバーを取得する必要があります (MemberInfo は GetHashCode を実装します。異なる型のメンバーを比較して機能するかどうかはわかりません。署名の型と名前だけを一致させるためにハッシュ オブジェクトが必要になる場合があります)。次に、新しいインターフェイスのメンバーをループするときに、ハッシュセットに存在しない場合にのみスタブ コードを生成します。

メンバーが存在する前に TypeBuilder でインターフェイスを宣言することは問題ではありません。ただし、メンバーが存在するまで CreateType を呼び出さない限り、署名のみを気にするため、基本型が実装する他のインターフェイスを気にする必要はありません。あなたの新しいインターフェイスと一致するメンバーの。

結果の型をインターフェイスと基本型でキャッシュする限り、パフォーマンスがまったく悪くないはずです。

于 2011-03-14T15:37:11.120 に答える
0

これは事実上、効率的な方法での名前と署名を比較する問題ですMemberInfosToStringMemberInfoを呼び出して、メンバーの名前と署名を含む文字列を取得できます。この文字列を使用して、2 つのメンバーが署名と同等であるかどうかを判断できます。文字列を に入れるHashSetと、比較は非常に効率的になります。

同等の署名文字列を構築するという事実は、オブジェクトToStringをシリアル化および逆シリアル化するために .NET フレームワークによって内部的に使用されますMemberInfoが、知る限り、これは実際には文書化されていません。したがって、この文書化されていない動作に依存したくない場合は、独自の署名文字列を作成して比較することができます。ただし、ジェネリック型パラメーターを考慮すると、これは非常に複雑になる可能性があることに注意してください。

于 2012-10-15T14:22:31.853 に答える