System.Action <t>作为EventHandler </t>

时间:2011-05-24 09:00:31

标签: c# .net action event-handling func

您是否相信使用委托System.Action或System.Func作为EventDelegates而不是经典的EventHandler模​​式。因此,我会遇到问题吗?

private bool disposed;

public event Action<IUnitOfWork, IContext> Disposing;

public void Dispose()
{
    if (this.disposed)
    {
        return;
    }

    if (null != this.Disposing)
    {
        this.Disposing(this, this.AttachedContext);
    }

    this.disposed = true;
}

-

用法:

unitOfWorkInstance.Disposing += (u, c) => c.Rollback(u); // in my opinion more readable than
unitOfWorkInstance.Disposing += (sender, args) => args.AttachedContext.Rollback(sender as IUnitOfWork);

抱歉可怕的englisch

3 个答案:

答案 0 :(得分:6)

嗯,你在那里提供的代码不是线程安全的 - 有人可以在你的无效测试之后和你的电话this.Disposing之前取消订阅事件处理程序。

但总的来说,它应该可以正常工作。缺点是,如果不遵循EventHandler约定,您可以订阅的内容略有限制。

例如,假设您有一个非常通用的事件处理程序方法:

public void LogEvent(object sender, EventArgs e)
{
    Console.WriteLine("Event raised");
}

您可以使用它来按照正常约定订阅任何事件 - 但不能使用 你的活动。

但这是一个相当小的缺点。我想一个可能更大的问题是它可能会混淆那些期待看到传统事件签名的开发人员。

编辑:我刚才记得其他一些图书馆可能会期待传统的事件签名 - 例如Reactive Extensions。 IIRC,订阅其他活动并非不可能,只是有点困难。

答案 1 :(得分:2)

从“代码工作”这个角度来看,我认为将这些委托类型用于事件是完全可以的。

执行此操作的问题在于,您没有遵循事件的公共模式,其中委托为EventHandler<TEventArgs>,而TEventArgs是包含事件参数的自定义类型。遵循这种模式的好处包括:

  • 代码可读性
  • 如果需要向事件添加参数,则无需更改事件订阅者(因为您只需将其添加到自定义事件参数类中)。

答案 2 :(得分:1)

一般情况下:

使用Action作为事件处理程序没有问题。它受语言支持,因此请使用它:)

我能想到的唯一情况是试图通过反射找到你的事件的代码。但是,如果该代码无法将任何委托作为事件类型处理,我会说他们的代码是错误的,而不是你的代码。

您的具体示例:

您正在使用的模式的问题是,在Dispose方法中,您不应该真正使用该对象。它有时可能是安全的,但很容易出错。

例如,如果Dispose方法在引发事件之前处置了资源,则该对象将处于不可用状态。

对于维护程序员来说,在编辑Dispose方法时,这可能很难(没有评论和强有力的代码审查)。

相关问题