获取匿名方法的目标

发布于 2024-11-26 14:20:51 字数 2363 浏览 2 评论 0原文

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

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

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

傻比既视感 2024-12-03 14:20:51

您(大概)看到 编译器生成的闭包类,其中包含匿名方法使用的变量。
此类具有特定命名的字段,来自父类的参考信息。

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文