Инициране на Събития(events) чрез Reflection в C#

април 25, 2008 от stefoo

Разработвайки проект, който използва много събития, ми се стори доста досадно за всяко едно събитие да се пише специален метод за актовиране. Като допълнително затруднение се появи и условието всеки метод, който се абонира за събитието, да се извиква индивидуално, т.е. да се използва InvocationList-а на събитието. Ето моето решение на проблема:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace NSVotingService
{
    public static class EventUtils
    {
        ///
        /// Иницира произволно въбитие.
        ///
        /// EventUtils.FireEvent(ownerObject, "SomethingChanged", args);
        /// Обектът собственик на събитието
        /// Наименование на събитието
        /// EventArgs
        ///
        public static void FireEvent(object eventOwner, string eventName, EventArgs args)
        {
            // Използва се за достъп до InvocationList-а на event-а
            //Чрез Reflection извлича информацията за полето на event-а
            FieldInfo filedInfo = eventOwner.GetType().GetField(eventName,
                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            //Използва се за премахване на делегата от
            //InvocationList-а ако възникне exception по време на изпълнението му
            EventInfo eventInfo = eventOwner.GetType().GetEvent(eventName);

            MulticastDelegate eventDelegate = (MulticastDelegate)filedInfo.GetValue(eventOwner);
            Delegate[] delegates = null;
            if (eventDelegate != null)
            {
                try
                {
                    //Извличаме InvocationList-а на събитието
                    delegates = eventDelegate.GetInvocationList();
                }
                catch (MemberAccessException e)
                {
                    throw e;
                }
                if (delegates != null)
                {
                    lock (eventOwner)
                    {
                        foreach (Delegate dlg in delegates)
                        {
                            try
                            {
                                dlg.Method.Invoke(dlg.Target, new object[] { eventOwner, args });
                            }
                            catch (Exception e)
                            {
                                //Нещо непредвидено се е случило
                                //Премахваме делегата от InvocationList-а на събитието
                                eventInfo.RemoveEventHandler(eventOwner, dlg);
                            }
                        }
                    }
                }
            }
        }
    }
}

още информация

If you need this in English please contact me.