2011-03-22 61 views
8

是否有存储的委托不绑定到一个对象怎么样,你可以用一个MethodInfo的一种方式?现在我正在存储一个MethodInfo,所以我可以给它一个调用该方法的对象。但我更希望它是一个代表。就像有一个属性告诉.net第一个参数是“this”?C#委托没有绑定到实例?

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

你可以改一下用多一点的细节问题,我想我懂了部分但不当然。 – 2011-03-22 23:52:14

+0

增加了我的意思的例子。基本上有可能有一个委托没有对象引用,并给它一个对象,当你打电话给它? – Will 2011-03-23 00:06:18

+1

我改变了你的问题的标题,使其更清晰。随意回滚,如果你不喜欢它;) – 2011-03-23 00:14:08

回答

11

你想要什么叫做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了解更多详情。

+0

C#不直接支持它。感谢您的信息:D。 – Will 2011-03-23 00:26:08

5

可以使用Delegate.CreateDelegate方法来创建一个强类型的代表为MethodInfo

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

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

(这就是所谓的钻营)

注意,这将仍然具有反射每个委托被调用时命中的表现,不像Delegate.CreateDelegate

+0

没有考虑使用lambda使它更好,谢谢。 – Will 2011-03-23 00:22:34

0

委托实质上只是一个MethodInfo(实际上,一个MethodBase)和一个对象引用,其中有一些内部指针用于执行。所以,如果你有一个MethodInfo,你实际上有一个未绑定的委托。你的具体用例是什么?

+1

在功能上,是的,它大致相同。但是MethodInfo.Invoke比调用代表... – 2011-03-23 00:15:21

+0

@Thomas Levesque的要慢得多:授予。对于重复呼叫,可以通过调用“委托”来改善性能。CreateDelegate()'来创建一个绑定的委托,但是我猜想对于绑定调用放弃绑定调用放弃模式,它不会提供任何性能优势。 – 2011-03-23 02:05:52

0

为什么不干脆

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

这样你就可以

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

甚至

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