获取匿名方法的目标

本文关键字:目标 方法 获取 | 更新日期: 2023-09-27 18:03:30

下列方法是基类的一部分,它使派生类能够指定应该由事件通知谁。

  protected void RaiseEvent<TEventArgs>(EventHandler<TEventArgs> updateEvent, TEventArgs eventArgs, UpdateReceivers updateReceivers) 
     where TEventArgs : EventArgs
  {
     EventHandler<TEventArgs> handler = updateEvent;
     if (handler != null)
     {
        if (updateReceivers.ToAllSubscribers)
        {
           handler(this, eventArgs);
        }
        else
        {
           NotifySpecifiedReceiver(handler, eventArgs, updateReceivers.Receiver);
        }
     }
  }
  private void NotifySpecifiedReceiver<TEventArgs>(EventHandler<TEventArgs> handler, TEventArgs eventArgs, object updateReceiver)
     where TEventArgs : EventArgs
  {
     foreach (Delegate @delegate in handler.GetInvocationList())
     {
        // is the delegates target our receiver?
        // but this doesnt work for anonymous methods :(
        if (@delegate.Target == updateReceiver)
        {
           try
           {
              @delegate.DynamicInvoke(this, eventArgs);
           }
           catch (Exception ex)
           {
           }
        }
     }
  }

为了只通知一个特定的接收者,方法是这样使用的:(接收者当然必须被订阅)

event EventHandler<SomethingChangedEventArgs> SomethingChanged;
RaiseEvent(SomethingChanged, args, UpdateReceivers.Single(receiver));

这只会引发委托"指向"接收者。

我这里的问题是,当我使用匿名方法订阅SomethingChanged事件,它不工作,当我使用这个事件来通知订阅它的对象

class EventConsumer
{
   private EventSource _eventSource;
   private void SubscribeEvents()
   {
       // ReactOnEvent() will not be called because the check [@delegate.Target == updateReceiver] doesnt work for anonymous methods
       _eventSource.MyStateChanged += (sender, e) => ReactOnEvent();
       _eventSource.PublishCurrentState(this);
   }
}
class EventSource
{
    // multiple objects are subscribed to this event
    event EventHandler<MyStateChangedEventArgs> MyStateChanged;
    public void GetCurrentState(object receiver)
    {
        // receiver ask for the current state, only raise event for him
        RaiseEvent(MyStateChanged, args, UpdateReceivers.Single(receiver));
    }
}

是否有可能获得包含匿名方法的实例?或者我应该用一种完全不同的方法来解决我的问题?

获取匿名方法的目标

您(大概)看到了编译器生成的闭包类,其中包含匿名方法使用的变量。
该类具有特定命名的字段,这些字段引用父类的信息。

您可以使用反射来查找编译器生成的DisplayClass (Target值)中名为<>4__this的字段,并获取其值以查找创建委托的类的实例。

但是,不这样做
这依赖于c#编译器的内部行为,该行为可能随时发生变化。

另外,闭包类包含的字段取决于匿名方法的位置和它引用的成员。如果匿名方法不使用类实例,它可能根本没有this字段。