1

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

  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));
    }
}

是否有可能获取包含匿名方法的实例?还是我应该使用完全不同的方法来解决我的问题?

4

1 回答 1

4

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

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

但是,不要这样做
这依赖于可能随时更改的 C# 编译器的内部行为。

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

于 2011-07-26T19:00:07.617 回答