気がつけば一ヶ月が過ぎてました。忙しかったしなぁ(いや、まだまだ忙しいぞ)。
備忘録として書き留めておきたいこともたくさん忘れてしまいました。
というわけで今回はリフレクションのお話。
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メソッドが使用できるのが、IsGemericMethodDefinitionがtrueのもののみなので、オープンジェネリック型からクローズジェネリック型の生成はできないのかな?