【问题标题】:Getting the target of an anonymous method获取匿名方法的目标
【发布时间】:2011-10-13 16:21:43
【问题描述】:

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

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

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

【问题讨论】:

  • 你不应该打电话给DynamicInvoke
  • 还有其他调用委托的方法吗?
  • @delegate(this, eventArgs) 您只需要 DynamicInvoke 来获取无类型委托。 (它使用反射来调用方法)
  • @delegate(this, eventArgs) 导致编译器错误 -> 'delegate' 是一个'变量',但用作'方法'
  • 需要声明为EventHandler&lt;TEventArgs&gt;

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


【解决方案1】:

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

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

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

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

【讨论】:

  • 好的,我想我将不得不接受这样一个事实,即这里不可能使用匿名方法。有没有办法在不使用反射的情况下确定委托是否是匿名方法?当有人使用匿名方法订阅时,这将有助于添加日志条目。
  • 检查Target是否为[CompilerGenerated]
猜你喜欢
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多