获得匿名方法的目标

时间:2011-07-26 18:50:38

标签: c# .net delegates anonymous-methods anonymous-delegates

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

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

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

1 个答案:

答案 0 :(得分:4)

您(大概)看到compiler-generated closure class包含匿名方法使用的变量。
该类具有specifically-named fields,它引用父类的信息。

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

然而,不要这样做 这依赖于C#编译器的内部行为,可能随时发生变化。

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