Jonが指摘しているように、以下は、タイプが実行時にDLRを介してメソッドを提供していると思われる場合にのみ実際に適用されます。ほとんどの単純なケースでは、反射が簡単になります。
dynamic
メソッド名はわかっているがターゲットはわかっていない場合を対象としています。メソッド名がわからない場合は、注意が必要です。トリッキーな点は、おそらく、コールサイトを維持して再利用できるようにすることです(これがDLRがパフォーマンスを維持する方法です)。生意気な方法の1つは、呼び出されたメソッドを追跡する静的ユーティリティクラスです。次に例を示します。パラメータを処理する必要がある場合は、非常に面倒になることに注意してください。
using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class Foo
{
public object Bar() { return "I was here"; }
}
static class Program
{
static void Main()
{
object obj = new Foo();
object result = DynamicCallWrapper.Invoke(obj, "Bar");
Console.WriteLine(result);
}
}
static class DynamicCallWrapper
{
// Hashtable has nice threading semantics
private static readonly Hashtable cache = new Hashtable();
public static object Invoke(object target, string methodName)
{
object found = cache[methodName];
if (found == null)
{
lock (cache)
{
found = cache[methodName];
if(found == null)
{
cache[methodName] = found = CreateCallSite(methodName);
}
}
}
var callsite = (CallSite<Func<CallSite, object,object>>)found;
return callsite.Target(callsite, target);
}
static object CreateCallSite(string methodName)
{
return CallSite<Func<CallSite, object, object>>.Create(
Binder.InvokeMember(
CSharpBinderFlags.None, methodName, null, typeof(object),
new CSharpArgumentInfo[] {
CSharpArgumentInfo.Create(
CSharpArgumentInfoFlags.None, null) }));
}
}