Разработвайки проект, който използва много събития, ми се стори доста досадно за всяко едно събитие да се пише специален метод за актовиране. Като допълнително затруднение се появи и условието всеки метод, който се абонира за събитието, да се извиква индивидуално, т.е. да се използва 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.