26

EventArgs为了将信息传递回调用事件的类而在事件处理程序中进行修改是否令人不悦?

例如,如果我有一个需要验证 SSL 证书的低级通信类,但它无法知道有效证书的外观,因为这是该类不同用户的知识。

class ValidationEventArgs : System.EventArgs
{
    public X509Certificate Certificate { get; set; }
    public bool Valid { get; set; }
}

然后在使用对象中,他们连接到事件,并检查它以某种方式更改Valid标志以指示证书是否可以接受。

comms.ValidationEvent += CertValidationHandler;
    
void CertValidationHandler(ValidationEventArgs args)
{
    if (args.Certificate.Issuer.Contains(COMPANY_NAME))
        args.Valid = true;
}

我找到了这样使用的参考EventArgs,但我也看到有人说不推荐。

编辑:也许我应该澄清这不是关于继承EventArgs,而是将它们用作双向沟通渠道。正如其他人评论的那样,这是可以接受的,无论谷歌听到什么反对意见,可能只是人们误解/误用了这个概念,现在与goto.

4

3 回答 3

44

问自己以下问题,“当我发布事件时,我是否希望任何订阅者更改任何 EventArgs 值”?如果答案是否定的,例如您正在广播只读信息,则使该类不可变,但是如果您需要订阅者的一些反馈,则使需要更改的属性可变。

为了澄清,在广播示例中,我们想告诉任何订阅者一些事情,但不让他们改变值。

public class ProgressEventArgs : EventArgs
{
    public ProgressEventArgs(int current)
    {
        this.Current = current;
    }

    public int Current { get; private set; }
}

Equally though, we could also raise an event to ask for information the class itself does not know.

public class FeedbackEventArgs : EventArgs
{
    public bool ShouldContinue { get; set; }
    public string Reason { get; set; }
}
于 2012-02-16T08:53:27.863 回答
10

You can use the EventArgs class through the Generic Types approach. In this sample, i will use the Rect class with as return type:

public EventHandler<Rect> SizeRectChanged;

Raising the event:

if(SizeRectChanged != null){
   Rect r = new Rect(0,0,0,0);
   SizeRectChanged(this,r);
}

Listening the event:

anyElement.SizeRectChanged += OnSizeRectChanged;

public void OnSizeRectChanged(object sender, Rect e){
    //TODO abything using the Rect class
    e.Left = e.Top = e.Width = e.Height = 50;
}
于 2013-11-13T10:43:28.947 回答
2

我不知道有任何反对继承自的建议EventArgs;据我所知,继承它是一种很好的做法。

作为一般原则,我建议您使派生类不可变。如果您需要,这将使线程之间的传递更加安全。最简单的方法是将你的属性声明为{ get; private set; },并且只在构造函数中设置它们。显然,对于问题中的特定用例,您无法做到这一点,但您应该在可能的情况下这样做。

于 2012-02-16T08:20:36.357 回答