首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >避免使用DynamicInvoke时使用MulticastDelegate作为参数

避免使用DynamicInvoke时使用MulticastDelegate作为参数
EN

Stack Overflow用户
提问于 2011-01-21 03:46:06
回答 3查看 1.6K关注 0票数 3

我有一个MulticastDelegate,它可以引用具有相同签名的许多(遗留)委托中的一个。例如:

代码语言:javascript
复制
public delegate void ObjectCreated(object sender, EventArgs args);
public delegate void ObjectDeleted(object sender, EventArgs args);
//...

然后使用这些委托来定义事件:

代码语言:javascript
复制
public event ObjectCreated ObjectWasCreated;
public event ObjectDeleted ObjectWasDeleted;

然后我有一个方法,它接受一个MulticastDelegate,我用它来做一些常见的检查:

代码语言:javascript
复制
void DispatchEvent(MulticastDelegate handler, object sender, EventArgs args)
{
    if (handler != null)
    {
        // ...
        handler.DynamicInvoke(sender, args);
    }
}

它是从定义事件的类的其他方法中调用的:

代码语言:javascript
复制
DispatchEvent(ObjectWasCreated, sender, args);
DispatchEvent(ObjectWasDeleted, sender, args);

有没有一种更简洁的方法来避免DynamicInvoke?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-21 05:19:21

这是我的无反射解决方案。它基本上实现了一个列表形式的多播委托。更少的代码?不是的。更好的性能?我不知道。清洁工?嗯。

代码语言:javascript
复制
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);
}
票数 2
EN

Stack Overflow用户

发布于 2013-06-04 16:32:39

一种简单的替代方法是使用内置类型,如Action<,>EventHandler,而不是自定义委托,这样您就可以获得强类型。

代码语言:javascript
复制
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);
    }
}

代码语言:javascript
复制
public static event EventHandler ObjectWasCreated;
public static event EventHandler ObjectWasDeleted;  

void DispatchEvent(EventHandler handler, object sender, EventArgs args) 
{
    if (handler != null)
    {
        // ...
        handler(sender, args);
    }
}

现在,您的方法调用将非常简单。

代码语言:javascript
复制
DispatchEvent(ObjectWasCreated, sender, args);
DispatchEvent(ObjectWasDeleted, sender, args);

但这大多不是一个好的解决方案。

您可以使用dynamic,但它仍然比DynamicInvoke好得多

代码语言:javascript
复制
void DispatchEvent(MulticastDelegate handler, object sender, EventArgs args) 
{
    if (handler != null)
    {
        // ...
        ((dynamic)handler)(sender, args);
    }
}

或者可以是泛型:

代码语言:javascript
复制
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

票数 1
EN

Stack Overflow用户

发布于 2011-01-21 04:46:04

你可以这样做:

代码语言:javascript
复制
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属性,但由于它们是事件,它们可能有多个订阅者……

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4751799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档