Одной простой альтернативой является использование встроенных типов, таких как Action<,>
или EventHandler
, вместо пользовательских делегатов, чтобы вы могли получить строгие типы.
public static event Action<object, EventArgs> ObjectWasCreated;
public static event Action<object, EventArgs> ObjectWasDeleted;
void DispatchEvent(Action<object, EventArgs> handler, object sender, EventArgs args)
{
if (handler != null)
{
// ...
handler(sender, args);
}
}
или
public static event EventHandler ObjectWasCreated;
public static event EventHandler ObjectWasDeleted;
void DispatchEvent(EventHandler handler, object sender, EventArgs args)
{
if (handler != null)
{
// ...
handler(sender, args);
}
}
Теперь ваш вызов метода будет простым.
DispatchEvent(ObjectWasCreated, sender, args);
DispatchEvent(ObjectWasDeleted, sender, args);
Но в большинстве случаев это не очень хорошее решение.
Вы можете использовать dynamic
, все еще намного лучше, чем DynamicInvoke
:
void DispatchEvent(MulticastDelegate handler, object sender, EventArgs args)
{
if (handler != null)
{
// ...
((dynamic)handler)(sender, args);
}
}
Или могут быть дженерики:
void DispatchEvent<T>(T handler, object sender, EventArgs args)
{
if (handler != null)
{
// ...
((dynamic)handler)(sender, args);
}
}
Я провел небольшое сравнение производительности и обнаружил, что dynamic
слишком хорошо на самом деле:
За миллион попыток
MulticastDelegate + dynamic (первый пример) => 40 мс
generic + dynamic (второй пример) => 90 мс
MulticastDelegate + DynamicInvoke (задано изначально) => 940 мс