web-dev-qa-db-ja.com

C#はSystem.Typeを汎用パラメーターとして使用します

データベースでクエリを実行する必要がある型のリスト(System.Type)があります。

このタイプごとに、次の拡張メソッド(LinqToNhibernateの一部)を呼び出す必要があります。

Session.Linq<MyType>()

ただし、MyTypeはありませんが、代わりにTypeを使用します。

私が持っているものは:

System.Type typeOne;

ただし、次のことはできません。

Session.Linq<typeOne>()

TypeをGenericパラメーターとして使用するにはどうすればよいですか?

75
Jan

直接、できません。ジェネリックのポイントは、compile-time型の安全性を提供することです。ここで、コンパイル時に関心のある型がわかっていて、その型のインスタンスを操作できます。あなたの場合、あなたはTypeしか知らないので、あなたが持っているオブジェクトがその型のインスタンスであるというコンパイル時のチェックを取得することはできません。

リフレクション経由でメソッドを呼び出す必要があります-このようなもの:

// Get the generic type definition
MethodInfo method = typeof(Session).GetMethod("Linq", 
                                BindingFlags.Public | BindingFlags.Static);

// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeOne);
// The "null" is because it's a static method
method.Invoke(null, arguments);

このタイプを頻繁に使用する必要がある場合は、必要な他のジェネリックメソッドを呼び出す独自のジェネリックメソッドを記述し、リフレクションでyourメソッドを呼び出す方が便利な場合があります。

81
Jon Skeet

これを行うには、リフレクションを使用する必要があります。

_typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);
_

Linq<T>()Session型の静的メソッドであると仮定)

Sessionが実際にオブジェクトである場合、Linqメソッドが実際に宣言されている場所を知り、Sessionを引数として渡す必要があります。 :

_typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});
_
28
Marc Gravell