C#Custom EventArgs问题

时间:2009-05-13 19:22:53

标签: c# asp.net events eventargs

我有一个自定义集合,我正在添加一个ValidateItem事件。只要在自定义集合中添加或更新项目,就会调用此ValidateItem事件。

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

但我正在试图弄清楚如何让活动的来电者知道发生了什么,以及如何传递有关背景的信息。

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

我是否应该添加我希望传递回Custom 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) 
派生类中的

方法。虽然我倾向于避免退出参数......

如果有人对每种方法的利弊有任何想法,我很乐意听到它们!

谢谢, 最大

6 个答案:

答案 0 :(得分:3)

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

由于它是一个覆盖此行为的继承类,因此该方法应标记为protected和virtual:

protected virtual bool Validate(object item);

我也不喜欢在参数上使用out,所以按照你最初的直觉来使用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;
}

使用此事件的优缺点是,当您要向多个订阅者发布操作或信息时,将使用事件。订阅者是您不了解的类。你不在乎他们是谁或他们做了什么。他们不应该真正将信息传递给通知类。他们应该只处理提供给他们的事件信息。

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

答案 1 :(得分:1)

我不认为你所描述的内容真的适合你通常会在活动中看到的观察者,可观察的模式。

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

答案 2 :(得分:0)

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

在这种情况下,如果你想进行不会抛出异常的验证,那么是的,我会将你需要的那些字段添加到自定义事件args中 - 它们已经是自定义的,所以没有理由不扩展它们以满足您的需求: - )

马克

答案 3 :(得分:0)

一些敏捷的想法:

我会使属性readonly符合eventargs类的“正常”模式。

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

一个问题:你如何使用EventArgs属性?

答案 4 :(得分:0)

自定义事件args专门用于向事件处理程序传递信息,因此,是的,它们是放置它们的好地方。

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

答案 5 :(得分:0)

EventArgs和CancelEventArgs没有任何成员将信息传递给订阅者。 因此,您通常会继承其中一个类并添加一个或多个成员来传递信息。 您还可以使您的类具有通用性,这样,只要您有不同的数据要发送,就不必创建新的EventArgs类。

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

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