2

我有一个要添加 ValidateItem 事件的自定义集合。每当在自定义集合中添加或更新项目时,都会调用此 ValidateItem 事件。

我希望允许派生类能够订阅事件并确定它们自己的逻辑来判断一个项目是否“有效”,如果它是“无效”的,则可能禁止将其添加到集合中。

但我试图弄清楚如何让事件的调用者知道发生了什么以及如何传递有关正在发生的事情的信息。

我的自定义 eventargs 继承自 CancelEventArgs,因此我能够使用它将 Cancel 位传递回调用者。但我从未见过以这种方式传回错误信息(错误代码、消息等)的任何情况,所以我想知道这是否不是最好的方法。

我是否应该添加任何我希望传递回自定义 eventargs 类的错误数据,是否有充分的理由支持或反对这一点?还是有其他更好的方法来实现这一点?

这是我的 eventargs 类:

public delegate void ItemValidationEventHandler(object sender, ItemValidationEventArgs e);

public class ItemValidationEventArgs : CancelEventArgs
{
    public ItemValidationEventArgs(object item, ObjectAction state, EventArgs e)
    {
        Item = item;
        State = state;
        EventArgs = e;
    }

    public ItemValidationEventArgs(object item, ObjectAction state) : this(item, state, new EventArgs())
    {
    }

    public ItemValidationEventArgs() : this(null, ObjectAction.None, new EventArgs())
    {
    }

    // is there a better way to pass this info?
    public string ErrorMessage {get; set;}
    public int ErrorNumber {get;set;}

    public object Item { get; private set; }
    public ObjectAction State { get; private set; }

    public EventArgs EventArgs { get; private set; }
}

更新:我想另一个选择是使用这样的东西:

virtual bool Validate(object item, ObjectAction action, out string errorMessage) 

派生类中的方法。虽然我倾向于避免输出参数......

如果有人对每种方法的优缺点有任何想法,我很想听听!

谢谢,马克斯

4

6 回答 6

3

为此使用事件可能不是最好的设计方法。

由于它是一个将覆盖此行为的继承类,因此该方法应标记为受保护的和虚拟的:

protected virtual bool Validate(object item);

我也不喜欢使用outon 参数,所以按照你最初的直觉使用EventArgs,你应该创建一个类来封装你的验证结果。

例子:

class ValidationResult
{
     public string ResultMessage{get;set;}
     public bool IsValid {get;set;}
}

您的方法将是:

protected virtual ValidationResult Validate(object item)
{
   ValidationResult result = new ValidationResult();

   // validate and set results values accordingly

   return result;
}

使用此 over 事件的优点和缺点是,当您想要向多个订阅者发布操作或信息时使用事件。订阅者是你一无所知的类。你不关心他们是谁或他们做什么。他们也不应该真正将信息传递回通知类。他们应该只处理提供给他们的事件信息。

在您的实例中,您继承的类是您唯一的订阅者。最重要的是,您希望能够将有用的信息传递回父类。继承更适合这种期望的行为,并且还允许您轻松实现不同类型的验证类。对于事件,您必须一遍又一遍地输入代码来附加事件处理程序(非常丑陋的 IMO)。

于 2009-05-13T21:58:28.607 回答
1

我认为您所描述的内容并不真正适合您通常在事件中看到的观察者、可观察模式。

由于这些是派生类,我可能会考虑虚拟化对象的验证方法并让孩子提供特定的验证例程。

于 2009-05-13T19:41:12.183 回答
0

好吧,如果您创建自己的自定义验证事件以及自定义验证事件参数,我会假设您更愿意传回状态/错误代码,而不是在某些事情没有验证时抛出异常。

在这种情况下,如果您想要进行不会引发异常的验证,那么是的,我会将您需要的那些字段添加到您的自定义事件参数中 - 它们已经是自定义的,因此没有理由不扩展它们以适合您的需要:-)

马克

于 2009-05-13T19:29:34.167 回答
0

几个快速的想法:

我会将属性设为只读以符合 eventargs 类的“正常”模式。

也许与错误信息相关的属性应该一起包装到某个 ErrorInformation 类中(这样可以更容易地将该信息传递给其他方法)。

一个问题:您使用 EventArgs 属性做什么?

于 2009-05-13T19:30:46.507 回答
0

自定义事件参数专门用于在事件处理程序之间传递信息,所以是的,它们是放置它们的好地方。

另一种选择是抛出异常 - 这是相当严厉的,但应该阻止其他事件处理程序为该事件执行。

于 2009-05-13T19:33:14.897 回答
0

EventArgs 和 CancelEventArgs 没有任何成员向订阅者传递信息。因此,您通常会从这些类之一继承并添加一个或多个成员来携带信息。您还可以使您的类成为通用类,这样当您有不同的数据要发送时,您就不必创建新的 EventArgs 类。

最后,您可以使用 ,而不是创建自己的 ItemValidationEventHandler 委托类型,EventHandler<T>其中 T 是 EventArgs 参数的类型。

此外,您不需要 EventArgs = e 成员。

于 2009-05-13T19:40:19.377 回答