我有一个MulticastDelegate,它可以引用具有相同签名的许多(遗留)委托中的一个。例如:
public delegate void ObjectCreated(object sender, EventArgs args);
public delegate void ObjectDeleted(object sender, EventArgs args);
//...然后使用这些委托来定义事件:
public event ObjectCreated ObjectWasCreated;
public event ObjectDeleted ObjectWasDeleted;然后我有一个方法,它接受一个MulticastDelegate,我用它来做一些常见的检查:
void DispatchEvent(MulticastDelegate handler, object sender, EventArgs args)
{
if (handler != null)
{
// ...
handler.DynamicInvoke(sender, args);
}
}它是从定义事件的类的其他方法中调用的:
DispatchEvent(ObjectWasCreated, sender, args);
DispatchEvent(ObjectWasDeleted, sender, args);有没有一种更简洁的方法来避免DynamicInvoke?
发布于 2011-01-21 05:19:21
这是我的无反射解决方案。它基本上实现了一个列表形式的多播委托。更少的代码?不是的。更好的性能?我不知道。清洁工?嗯。
public delegate void ObjectCreated(object sender, EventArgs args);
public delegate void ObjectDeleted(object sender, EventArgs args);
public event ObjectCreated ObjectWasCreated
{
add
{
m_ObjectCreatedSubscribers.Add(value.Invoke);
}
remove
{
m_ObjectCreatedSubscribers.RemoveAll(e => e.Target.Equals(value));
}
}
public event ObjectDeleted ObjectWasDeleted
{
add
{
m_ObjectDeletedSubscribers.Add(value.Invoke);
}
remove
{
m_ObjectDeletedSubscribers.RemoveAll(e => e.Target.Equals(value));
}
}
private List<Action<object, EventArgs>> m_ObjectCreatedSubscribers = new List<Action<object, EventArgs>>();
private List<Action<object, EventArgs>> m_ObjectDeletedSubscribers = new List<Action<object, EventArgs>>();
void DispatchEvent(List<Action<object, EventArgs>> subscribers, object sender, EventArgs args)
{
foreach (var subscriber in subscribers)
subscriber(sender, args);
}发布于 2013-06-04 16:32:39
一种简单的替代方法是使用内置类型,如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 +动态(第一个示例) => 40 ms
通用+动态(第二个示例) => 90 ms
MulticastDelegate + DynamicInvoke (最初有问题) => 940 ms
发布于 2011-01-21 04:46:04
你可以这样做:
void DispatchEvent(MulticastDelegate handler, object sender, EventArgs args)
{
EventHandler eventHandler =
(EventHandler)Delegate.CreateDelegate(typeof(EventHandler), handler.GetType().GetMethod("Invoke"));
eventHandler(sender, args);
}不过,我不确定这是否会比使用DynamicInvoke更快。
你必须在某个地方使用反射。如果每个委托可以保证只有一个订阅者,那么您可以在创建EventHandler时直接使用Delegate.Method属性,但由于它们是事件,它们可能有多个订阅者……
https://stackoverflow.com/questions/4751799
复制相似问题