.NET - удалить все обработчики событий слушателя из объекта - PullRequest
0 голосов
/ 16 февраля 2012

У меня есть objectRaiser, который может публиковать события, например, событие «PropertyChanged». У меня тоже есть другой objectListener, который прослушивает вызванные события из первого objectRaiser.

Как я могу удалить прослушиватели обработчиков событий с помощью objectListener из экземпляра objectRaiser?

Мне нужно повторить что-то важное: обработчики событий для удаления взяты из objectListener. Не работает для меня удалить все публикации из objectRaiser. Я смотрю на это в других вопросах, но не вижу решения моей проблемы.

С уважением и большое спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 16 февраля 2012

Я не уверен, что это именно то, что вам нужно ... но в приведенном ниже коде мы можем использовать Reflection для удаления обработчиков из экземпляра ObjectRaiser, содержащегося в ObjectListener:

namespace ObjectEvents
{
    class Program
    {
        private class ObjectRaiser
        {
            public event EventHandler PropertyChange;

            private string name;
            public string Name
            {
                get
                {
                    return name;
                }
                set
                {
                    name = value;
                    PropertyChange(this, new EventArgs());
                }
            }
        }

        private class ObjectListener
        {
            private ObjectRaiser or;

            public ObjectListener(ObjectRaiser or)
            {
                this.or = or;
                or.PropertyChange += new EventHandler(PropertyChange);
            }

            public void PropertyChange(object sender, EventArgs e)
            {
                Console.WriteLine("I'm listening!");
            }

            public void RemoveHandlers()
            {
                var lfi = or.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

                foreach(var fi in lfi)
                {
                    var eh = fi.GetValue(or) as EventHandler;
                    if (eh != null)
                    {
                        foreach (var del in eh.GetInvocationList())
                        {
                            foreach (var ev in or.GetType().GetEvents())
                            {
                                ev.GetRemoveMethod().Invoke(or, new object[] { del });
                            }
                        }
                    }
                }
            }
        }

        static void Main(string[] args)
        {
            var or = new ObjectRaiser();
            var ol = new ObjectListener(or);

            //This will raise the event
            or.Name = "New Name";
            ol.RemoveHandlers();
            //This will throw an exception because the event has no handler associated
            or.Name = "Weird Name";

            Console.ReadLine();
        }
    }
}

Примечание: это очень простой пример, который, безусловно, потребует значительных изменений для реального использования.

0 голосов
/ 16 февраля 2012

Изнутри objectRaiser:

MyEvent = null;

Со стороны: вы не можете, потому что у вас нет доступа к делегату, который хранит обработчики. Однако вы можете добавить общедоступный метод ClearHandlers() в objectRaiser и вызывать его из любого места.

...