作成時にインスタンスを指定せずに、インスタンスメソッドのデリゲートを作成できますか?つまり、メソッドが呼び出されるインスタンスを最初のパラメーターとして受け取る「静的」デリゲートを作成できますか?
たとえば、リフレクションを使用して次のデリゲートを作成するにはどうすればよいですか?
Func<int, string> = i=>i.ToString();
methodInfo.Invokeを使用できることは知っていますが、これは遅く、呼び出されるまで型の正しさをチェックしません。
MethodInfo
特定の静的メソッドのを持っている場合、を使用してデリゲートを構築することが可能Delegate.CreateDelegate(delegateType, methodInfo)
であり、静的メソッドのすべてのパラメーターはフリーのままです。
Jon Skeetが指摘したように、メソッドが参照型で非仮想である場合は、同じものを適用してインスタンスメソッドのオープンデリゲートを作成できます。仮想メソッドで呼び出すメソッドを決定するのは難しいので、それほど簡単ではなく、値型はまったく機能しないように見えます。
値型の場合、CreateDelegate
非常に奇妙な動作を示します。
var func37 = (Func<CultureInfo,string>)(37.ToString);
var toStringMethod = typeof(int).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, new Type[] {typeof(CultureInfo) }, null);
var func42 = (Func<CultureInfo,string>)Delegate.CreateDelegate(typeof(Func<CultureInfo,string>), 42, toStringMethod,true);
Console.WriteLine( object.ReferenceEquals(func37.Method,func42.Method)); //true
Console.WriteLine(func37.Target);//37
Console.WriteLine(func42.Target);//42
Console.WriteLine(func37(CultureInfo.InvariantCulture));//37
Console.WriteLine(func42(CultureInfo.InvariantCulture));//-201040128... WTF?
インスタンスメソッドが値型に属している場合、ターゲットオブジェクトとしてCreateDelegate
withを呼び出すと、バインディング例外がスローされます(これは参照型で機能します)。null
数年後のフォローアップ:私の例ではなく、誤ってバインドされたターゲットがfunc42(CultureInfo.InvariantCulture);
戻ってきたのは、リモートでコードが実行される可能性のあるメモリの破損でした(cve-2010-1898)。これは、2010年にms10-060セキュリティアップデートで修正されました。現在のフレームワークは42を正しく印刷します!それはこの質問に答えるのを簡単にすることはありませんが、例の特に奇妙な振る舞いを説明しています。"-201040128"
"42"