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

发布于 2024-08-28 02:22:04 字数 395 浏览 12 评论 0原文

我需要知道哪些处理程序订阅了 ObservableCollection 类的 CollectionChanged 事件。我发现的唯一解决方案是在事件的委托上使用 Delegate.GetInitationList() 。问题是,我无法让反射找到编译器生成的委托。据我所知,代表与事件具有相同的名称。我使用了以下代码:

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

I need to know what handlers are subsribed to the CollectionChanged event of the ObservableCollection class. The only solution I found would be to use Delegate.GetInvocationList() on the delegate of the event. The problem is, I can't get Reflection to find the compiler generated delegate. AFAIK the delegate has the same name as the event. I used the following piece of code:

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

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

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

发布评论

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

评论(2

瑕疵 2024-09-04 02:22:04

它不是一个属性,而是一个字段。这有效:

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

不要使用它。

It is not a property, it is a field. This works:

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

Don't use it.

樱花落人离去 2024-09-04 02:22:04

事件的全部要点是它们封装了发布/订阅性质,而不暴露当前订阅的处理程序。您不需要知道订阅的处理程序 - 如果您知道,则应该使用您自己的类型而不是 ObservableCollection。你想做什么?

没有什么可以保证存在编译器生成的委托字段。它可能没有使用类似字段的事件来声明 - 事实上,甚至可能根本没有用于支持委托的单个字段。 (考虑到 ObservableCollection 上没有太多事件,因此可能存在这种情况 - 但 WinForms 控件使用延迟分配的映射来避免每个事件必须有一个字段,而大多数事件都没有订阅处理程序.)

The whole point of events is that they encapsulate the publish/subscribe nature without exposing the currently subscribed handlers. You shouldn't need to know the subscribed handlers - if you do, you should use your own type instead of ObservableCollection. What are you trying to do?

There's nothing to guarantee that there is a compiler-generated delegate field. It may not have been declared using a field-like event - indeed, there may not even be a single field for the backing delegate at all. (There probably is, given that there aren't many events on ObservableCollection - but WinForms controls use a lazily allocated map to avoid having to have one field per event, when most events won't have subscribed handlers.)

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