泥庭

2010年12月2日

ジェネリックメソッドとリフレクション

Filed under: .NET — タグ: , — yone64 @ 12:37 午前

気がつけば一ヶ月が過ぎてました。忙しかったしなぁ(いや、まだまだ忙しいぞ)。
備忘録として書き留めておきたいこともたくさん忘れてしまいました。

というわけで今回はリフレクションのお話。

public class Hoge
{
    public object GetObject()
    {
        return null;
    }

    public T GetObject<T>()
    {
        return default(T);
    }
}

こんなクラスが定義されていた場合、下記は実行時エラーになります。

var method = typeof(Hoge).GetMethod("GetObject");

//System.Reflection.AmbiguousMatchException
//あいまいな一致が見つかりました。

GetMethodメソッドのオーバーロードを探してもジェネリックメソッドと非ジェネリックメソッドを区別できる物はない。どうやら、GetMethodで全部取得した後、チェックするしかないらしい。
この場合なら、次の通りです。

var method = typeof(Hoge).GetMethods().Single(m => m.Name == "GetObject" && m.IsGenericMethodDefinition);

なお、ジェネリックパラメータやメソッド引数が異なるオーバーロードがある場合は、

method.GetGenericArguments();
method.GetParameters();

などのメソッドからとれる値を比較して調べる必要があります。

ところで、MethodInfoクラスにはIsGenericMethodプロパティーとIsGenericMethodDefinitionがあります。違いが気になったのでMSDNで調べてみました。
http://msdn.microsoft.com/ja-jp/library/system.reflection.methodinfo.isgenericmethod(v=VS.80).aspx

var methodDefinition = typeof(Hoge).GetMethods().Single(m => m.Name == "GetObject" && m.IsGenericMethodDefinition);
Console.WriteLine(methodDefinition.IsGenericMethod);            //true
Console.WriteLine(methodDefinition.IsGenericMethodDefinition);  //true
Console.WriteLine(methodDefinition.ContainsGenericParameters);  //true

var openConstructed = methodDefinition.MakeGenericMethod(typeof(List<>));
Console.WriteLine(openConstructed.IsGenericMethod);            //true
Console.WriteLine(openConstructed.IsGenericMethodDefinition);  //false
Console.WriteLine(openConstructed.ContainsGenericParameters);  //true

var closeConstructed = methodDefinition.MakeGenericMethod(typeof(int));
Console.WriteLine(closeConstructed.IsGenericMethod);            //true
Console.WriteLine(closeConstructed.IsGenericMethodDefinition);  //false
Console.WriteLine(closeConstructed.ContainsGenericParameters);  //false

MakeGenericTypeメソッドが使用できるのが、IsGemericMethodDefinitiontrueのもののみなので、オープンジェネリック型からクローズジェネリック型の生成はできないのかな?

WordPress.com Blog.