Получить сгенерированный компилятором делегат для события - PullRequest
1 голос
/ 08 апреля 2010

Мне нужно знать, какие обработчики подписаны на событие CollectionChanged класса ObservableCollection. Единственное решение, которое я нашел, - это использовать Delegate.GetInvocationList () для делегата события. Проблема в том, что я не могу заставить Reflection найти делегат, сгенерированный компилятором. AFAIK делегат имеет то же имя, что и событие. Я использовал следующий кусок кода:

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

Ответы [ 2 ]

4 голосов
/ 08 апреля 2010

Это не свойство, это поле. Это работает:

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 голос
/ 08 апреля 2010

Весь смысл событий в том, что они инкапсулируют природу публикации / подписки без , выставляя обработчики, подписанные в данный момент.Вам не нужно знать подписанные обработчики - если вы это делаете, вы должны использовать свой собственный тип вместо ObservableCollection.Что вы пытаетесь сделать?

Ничто не может гарантировать, что является сгенерированным компилятором полем делегата.Возможно, он не был объявлен с использованием события, подобного полю, - на самом деле, может даже не быть ни одного поля для делегата поддержки.(Вероятно, это так, учитывая, что на ObservableCollection не так много событий - но элементы управления WinForms используют лениво распределенную карту, чтобы избежать необходимости иметь одно поле на событие, когда большинство событий не будет иметь обработчиков с подпиской.)

...