14

Reflection.Emitタイプ管理でさらに厄介な瞬間があります。

MyTypeたとえば、動的に生成されたアセンブリで定義されているという名前のタイプがあります。MyType.GetMethods()結果を呼び出すとNotSupportedException、が発生します。これにより、独自のラッパーとルックアップテーブルのセットを作成する必要がなくなりました。GetMethods()ただし、自分の型を汎用引数として使用する標準の汎用型でメソッドを呼び出したり、他の内省的なメソッドを呼び出したりする場合も、同じことが起こります。

  • Tuple<int, string>=>正常に動作します
  • Tuple<int, MyType>=>例外

ジェネリック型の定義からメソッドリストを取得できます。

typeof(Tuple<int, MyType).GetGenericTypeDefinition().GetMethods()

ただし、メソッドには実際の値(など)ではなく一般的なプレースホルダーがT1ありTResult、一般的な引数を元の値にさかのぼる別のクラッジを書く気はありません。

コードのサンプル:

var asmName = new AssemblyName("Test");
var access = AssemblyBuilderAccess.Run;
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, access);
var module = asm.DefineDynamicModule("Test");

var aType = module.DefineType("A");
var tupleType = typeof(Tuple<,>);
var tuple = tupleType.MakeGenericType(new [] { typeof(int), aType });

tuple.GetProperty("Item1"); // <-- here's the error

したがって、質問は次のとおりです。

  1. タイプが安全に呼び出せるGetMethods()かどうか、および同様のメソッドを検出するにはどうすればよいですか?
  2. タイプが安全でない場合、メソッドの実際のリストとその汎用引数値を取得するにはどうすればよいですか?
4

2 に答える 2

7

フォローアップの質問で回答を得ました。このTypeBuilderクラスには、次のことを正確に実行する一連の静的オーバーロードがあります。

var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());

不思議なことに、の過負荷はありませんGetProperty。ただし、プロパティのゲッターとセッターは、次を使用して解決できますGetMethod

var genericGetter = typeof(Tuple<,>).GetProperty("Item1").GetMethod;
var actual = TypeBuilder.GetMethod(myTuple, genericGetter);
于 2013-03-28T05:53:31.373 に答える
4

ドキュメントを参照します。

リフレクションエミットを使用したタイプの定義

それは言う

TypeBuilderはTypeから派生していますが、Typeクラスで定義された抽象メソッドの一部はTypeBuilderで完全には実装されていません。これらのTypeBuilderメソッドは、NotSupportedExceptionをスローします。Type.GetTypeまたはAssembly.GetTypeを使用して作成されたタイプを取得し、取得されたタイプを反映することにより、目的の機能を取得できます。

それで:

型がGetMethods()および同様のメソッドを安全に呼び出すことができるかどうかを検出するにはどうすればよいですか?

タイプオブジェクトがTypeBuilderである場合、またはタイプがTypeBuilderである任意のタイプを参照している場合、そうすることは安全ではありません。

タイプが安全でない場合、メソッドの実際のリストとその汎用引数値を取得するにはどうすればよいですか?

もう一度ドキュメントを参照します。実際にタイプをアセンブリに放出してから、アセンブリから取り出します。

于 2013-03-26T21:15:02.123 に答える