C#simple Event Raising – 使用“sender”与自定义EventArgs

考虑这种情况。 我有一个对象,让我们称它为…… Foo。 Foo引发了一个名为“Loaded”的简单事件。 作为活动信息的一部分,消费者需要知道哪个foo对象引发了该事件。 我们的团队采用了以下模式。

1)创建一个inheritance自EventArgs的新类 – 例如,FooEventArgs:System.EventArgs。

2)将类型为Foo的属性添加到FooEventArgs中,该属性通过构造函数传入来设置。

3)使用EventHandler的通用版本声明事件,所以

public event EventHandler Loaded; 

4)使用以下签名从Foo类提升事件:

 Loaded(this, new FooEventArgs(this)); 

本质上它的作用是使“发送者”成为foo对象,但它将foo对象引用作为强类型属性放入事件参数中。

这样做的一个优点是,当他们处理事件时,没有人必须打扰“发送者”,这降低了事件消费者和事件提升者之间的耦合。 另一个“优点”是,如果事件提升者的类型必须改变,因此强类型属性(希望永远不会发生),那么当它出现为null时,不是简单地让代码开始失败, API实际上已经破解,因此可以在编译时修复。

对我来说,这种模式似乎有点矫枉过正。 他们应该更多地信任“sender”参数,并放弃自定义事件参数吗? 我的团队认为没有人真正使用sender参数。 传递对事件提升对象的引用的最佳实践是什么?

编辑:到目前为止很棒的反馈,我会在接受之前将其打开一天左右。

常见的模式是使用发件人而不是将发件人单独添加到EventArgs。 自定义EventArgs用于其他状态,如树事件的树节点,可取消事件的(可设置)布尔值等。

我们使用共同模式,因为它也被BCL类使用,并且对“自制事件”产生影响可能会令人困惑。 此外,我们有一个全局IoC发布者 – 订阅者模式,但这个模式仅适用于普通的EventHandler委托签名,因为事先不知道类型。 在这种情况下,无论如何都需要强制转换(例如自定义EventArgs),因此我们也可以投射发送者。

我不认为这有点矫枉过正。 我同意您声明拥有单独的FooEventArgs类的优势。 这样做的另一个好处是,如果您将来需要向事件添加更多信息,您可以向FooEventArgs添加更多属性,而无需更改委托。

我会说你删除EventArgs的子类并使用sender属性来标识事件的发送者。 我认为遵循约定的论点是有价值的,但EventArgs中的参数不是必需的。 我个人会删除它,只使用sender属性。

如果您想将其作为强类型传递,您还可以创建一个自定义委托以用于您的活动…

 public delegate void LoadedHandler(FooEventArgs args); 

这样你就可以把它作为一个强大的类型…重用代表是很好的,但如果它们不适合你想要做的事情,你不应该只觉得只使用内置的代理。

我会说惯例有很多内容。 从长远来看,维持较少 – 尤其是 如果你有新人

我想这在某种程度上是偏好问题,但在我看来,当我读到consumers will need to know which foo object raised the event. 我立刻认为你可以从发送者参数中获取引发事件的对象,那么问题是什么?

你的团队有一些有效点(具有强类型属性),但我会说,从长远来看,使用框架指南而不是发明自己的指导将是一个更好的决定。

至于推荐的做法,我在Windows Workflow Foundation中看到null作为发送者提供了很多。 理想情况下,您的订阅者应该忘记引发事件的对象。

因此,如果您需要将调用者对象作为一个整体传递给处理程序,则必须将其放在EventArgs派生的对象中。 或者,我更喜欢明确传递事件提升者/调用者状态的点点滴滴而不是整个事物。

好吧,有时候更容易想到dotNET 1.1,在哪里

 Control.Invoke() 

被频繁使用

 int i;