C#委托没有绑定到实例?

时间:2011-03-22 23:47:45

标签: c#

有没有办法存储委托而不将它绑定到一个对象,就像使用MethodInfo一样?现在我正在存储一个MethodInfo,所以我可以给它调用方法的对象。但我更愿意让它成为代表。就像有一个属性告诉.net第一个参数是“this”吗?

MethodInfo mi;
Action<string> func;
mi.Invoke(this,new object[]{str});
func(this, str); //Is this possible with a delegate?

4 个答案:

答案 0 :(得分:13)

您想要的是open instance delegate。它不直接在C#语言中支持,但CLR支持它。

基本上,开放实例委托与普通委托相同,但在正常参数之前需要this的额外参数,并且具有空目标(如静态方法的委托)。例如,等效于Action<T>的开放实例将是:

delegate void OpenAction<TThis, T>(TThis @this, T arg);

这是一个完整的例子:

void Main()
{
    MethodInfo sayHelloMethod = typeof(Person).GetMethod("SayHello");
    OpenAction<Person, string> action =
        (OpenAction<Person, string>)
            Delegate.CreateDelegate(
                typeof(OpenAction<Person, string>),
                null,
                sayHelloMethod);

    Person joe = new Person { Name = "Joe" };
    action(joe, "Jack"); // Prints "Hello Jack, my name is Joe"
}

delegate void OpenAction<TThis, T>(TThis @this, T arg);

class Person
{
    public string Name { get; set; }

    public void SayHello(string name)
    {
        Console.WriteLine ("Hi {0}, my name is {1}", name, this.Name);
    }
}

有关详细信息,请查看this article

答案 1 :(得分:5)

您可以使用Delegate.CreateDelegate方法为MethodInfo创建强类型委托。

如果在编译时不知道方法的签名,可以使用Reflection创建Func<...>,或者创建一个调用MethodInfo的lambda表达式:

MethodInfo methodInfo = ...;
object thisObj = ...;
Func<object[]> callMethod = args => methodInfo.Invoke(thisObj, args);

(这叫做currying)

请注意,与Delegate.CreateDelegate不同,每次调用委托时,仍然会从反射中获得性能。

答案 2 :(得分:1)

委托本质上只是一个MethodInfo(实际上是一个MethodBase)和一个对象引用,带有一些内部性能指针。因此,如果您有MethodInfo,那么您基本上拥有一个未绑定的委托。您的具体用例是什么?

答案 3 :(得分:1)

为什么不简单

Action<T, string> unbound = (This, str) => This.Method(str);

所以你可以

unbound(instanceA, "hello");
unbound(instanceB, "world");

甚至

Action<string> bound = str => unbound(instanceC, str);