How can I extract the “real” target from an Event Handler that was defined anonymously?

我只是一个虾纸丫 提交于 2019-12-11 10:47:50

问题


Follow up to my question here:

According to a comment made -

The compiler creates a class member with a fictitious name and attaches it just as you would attach a declared method.

I do not fully comprehend what this means but I can verify that if instead of saying

Foo.Bar += (S, E) => { /*Code Goes Here*/ }

I instead say

Foo.Bar += FooBar;

private void FooBar( object sender, EventArgs e ){
    /*Code Goes Here*/
}

then Event.Target changes from WhatIsThis.App.<>c to WhatIsThis.App.

That's awesome but I can't guarantee that I will always write an actual method to attach to an event handler.

In the cases where I do use an anonymous method, is there a way to extract the real target, or am I just pigeonholed into using defined methods (I mean, I can live with that I guess but if there's some high-tech sorcery that I can employ to extract the real target, then I'm all for it ).


回答1:


do not fully comprehend what this means

Let's fix your comprehension. Suppose you have:

class C 
{
  int x;
  void M(int y) 
  { 
    int z = GetZ(); 
    Func<int, int> f = q => q + x + y + z;
    ... 

f is a delegate. It has a receiver and a method that is a method of the receiver. (Note, this is not actually a strict requirement but the corner case is obscure for our purposes today.)

What type is the receiver that has that method?

Can it be C, with the receiver equal to this? No. Why not? Because then how do we keep track of the value of y and z? There could be a different value for every invocation of M, so the receiver cannot be this.

What the compiler does is generates a new class:

class C 
{
  int x;
  class Locals
  {
    public C __this;
    public int y;
    public int z;
    public int A(int q) { return q + __this.x + y + z; }
  }

  void M(int y) 
  {
    Locals locals = new Locals();
    locals.__this = this;
    locals.y = y;
    locals.z = GetZ(); 
    Func<int, int> f = locals.A;
    ... 

So what is the receiver? the value of locals. What is the method? A.

Of course both Locals and A are given crazy names so that you cannot call them by accident.

In the cases where I do use an anonymous method, is there a way to extract the real target

You are extracting the real receiver, I promise.

'm working on an extension to do some things with Event Handlers and I need to be able to discern what an event handlers target is

Please don't do that. The receiver of an event handler is an implementation detail of the code that provided the handler. It's not there for you to make decisions on. Compilers are well within their rights to make any choice they like when generating a receiver for an event handler, and they do. Consider what happens if the event handler was created inside an iterator block, or an async method, for example. Or the event is being subscribed by some reactive extensions code that is applying sequence operations to the event. Again, the compiler will be generating classes all over the place. You can't rely on the class being something "sensible".

The thing you can rely on is: the subscriber wished the given method to be called when something happened. That's the contract you must obey; don't try to second-guess the subscriber.



来源:https://stackoverflow.com/questions/35759749/how-can-i-extract-the-real-target-from-an-event-handler-that-was-defined-anony

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!