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

时间:2009-04-30 23:42:41

标签: c# events

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

1)创建一个继承自EventArgs的新类 - 例如,     FooEventArgs:System.EventArgs。

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

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

public event EventHandler<FooEventArgs> Loaded;

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

Loaded(this, new FooEventArgs(this));

基本上它的作用是使“sender”成为foo对象,但它将foo对象引用作为强类型属性放入event参数中。

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

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

编辑:到目前为止反馈很好,我会在接受之前将其保留一天左右。

6 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

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

public delegate void LoadedHandler(FooEventArgs args);

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

答案 3 :(得分:3)

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

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

嗯,有时候更容易想到dotNET 1.1,其中

Control.Invoke()

经常使用

int i;

答案 4 :(得分:2)

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

答案 5 :(得分:2)

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

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