开发者

Getting the target of an anonymous method

开发者 https://www.devze.com 2023-03-23 15:26 出处:网络
The following methods are part of a base class which enables derived classes to specify who should be notified by an event.

The following methods are part of a base class which enables derived classes to specify who should be notified by an event.

  protected void RaiseEvent<TEventArgs>(EventHandler<TEventArgs> updateEvent, TEventArgs eventArgs, UpdateReceivers updateReceivers) 
     where TEventArgs : EventArgs
  {
     EventHandl开发者_JS百科er<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)
           {
           }
        }
     }
  }

To notify only a specific receiver, the method is used like this: (the receiver has to be subscribed of course)

event EventHandler<SomethingChangedEventArgs> SomethingChanged;

RaiseEvent(SomethingChanged, args, UpdateReceivers.Single(receiver));

This will only raise the delegates "pointing" to the receiver.

My problem here is when i use a anonymous method to subscribe to the SomethingChanged event its doesnt work when i use this event to notify the object which subscribed to it.

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

Is it possible the get the instance containing a anonymous method? or should i use a complete different approach to solve my problem?


You're (presumably) seeing the compiler-generated closure class that contains variables used by the anonymous method.
This class has specifically-named fields that reference information from the parent class.

You can use reflection to find a field in the compiler-generated DisplayClass (the Target value) named <>4__this, and get its value to find the instance of the class that created the delegate.

However, don't do this.
This relies on an internal behavior of the C# compiler that may change at any time.

Also, the fields contained by the closure class depend on where the anonymous method is and what members it references. If the anonymous method doesn't use the class instance, it may not have a this field at all.

0

精彩评论

暂无评论...
验证码 换一张
取 消