为事件获取编译器生成的委托

时间:2010-04-08 09:02:48

标签: c# reflection compiler-construction delegates observablecollection

我需要知道哪些处理程序被包含在ObservableCollection类的CollectionChanged事件中。我找到的唯一解决方案是在事件的委托上使用Delegate.GetInvocationList()。问题是,我无法得到Reflection来查找编译器生成的委托。 AFAIK代表与事件同名。我使用了以下代码:

PropertyInfo notifyCollectionChangedDelegate = collection.GetType().GetProperty("CollectionChanged", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);

2 个答案:

答案 0 :(得分:4)

它不是属性,而是属性。这有效:

using System;
using System.Collections.ObjectModel;  // Add reference to WindowsBase
using System.Collections.Specialized;
using System.Reflection;

namespace ConsoleApplication1 {
  class Program {
    static void Main(string[] args) {
      var coll = new ObservableCollection<int>();
      coll.CollectionChanged += coll_CollectionChanged;
      coll.Add(42);
      FieldInfo fi = coll.GetType().GetField("CollectionChanged", BindingFlags.NonPublic | BindingFlags.Instance);
      NotifyCollectionChangedEventHandler handler = fi.GetValue(coll) as NotifyCollectionChangedEventHandler;
      handler.Invoke(coll, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    static void coll_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
      Console.WriteLine("Changed {0}", e.Action);
    }
  }
}

不要使用它。

答案 1 :(得分:1)

事件的重点在于它们封装了发布/订阅性质,而没有公开当前订阅的处理程序。您不应该知道订阅的处理程序 - 如果这样做,您应该使用自己的类型而不是ObservableCollection。你想做什么?

没有什么可以保证编译器生成的委托字段。它可能没有使用类似字段的事件声明 - 实际上,甚至可能根本没有单独的字段用于支持委托。 (可能有,假设ObservableCollection上没有很多事件 - 但WinForms控件使用一个懒惰分配的映射来避免每个事件都有一个字段,而大多数事件都没有订阅处理程序。)< / p>