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

By 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.

Етикети: , ,

Вашият коментар