C# 注册到";这";对象';s自己的事件处理程序在“中”;这";方法

C# 注册到";这";对象';s自己的事件处理程序在“中”;这";方法,c#,.net,events,C#,.net,Events,我想为“Authenticator”(以下简称“objAuthenticator”)实例生成的事件提供deafult实现 这是一种可接受的做法,提供这样一种方法,即注册以处理objAuthenticator自己的事件,从而提供deafult实现 此外,如果这是一个可以接受的做法,我还有两个后续问题。 对于“SendEmailOnAuthenticationFailed”,我有两个重载方法 我应该向外界透露哪一个 哪一个会减少类之间的耦合 public class Authenticator {

我想为“Authenticator”(以下简称“objAuthenticator”)实例生成的事件提供deafult实现

这是一种可接受的做法,提供这样一种方法,即注册以处理objAuthenticator自己的事件,从而提供deafult实现

此外,如果这是一个可以接受的做法,我还有两个后续问题。 对于“SendEmailOnAuthenticationFailed”,我有两个重载方法

  • 我应该向外界透露哪一个
  • 哪一个会减少类之间的耦合

    public class Authenticator
    {
            public event EventHandler AuthenticationFailed = delegate { };
            protected virtual void OnAuthenticationFailed()
            {
                var handler = AuthenticationFailed;
                handler(this, EventArgs.Empty);
            }
    
            public void IsAuthenticated()
            {
                // Some logic...
                // ...
                // Woops authentication failed
                OnAuthenticationFailed();
            }
    
    
            // Is this a better option?
            public void SendEmailOnAuthenticationFailed()
            {
                SendEmailOnAuthenticationFailed(EmailSender);
            }
    
            // Or is this?
            public void SendEmailOnAuthenticationFailed(EventHandler emailSender)
            {
                AuthenticationFailed += emailSender;
            }
    
            private void EmailSender(object sender, EventArgs e)
            {
                Console.WriteLine("Send email: EmailSender");
            }
        }
    
[更新]:对Marc Gravell问题的回答

我对您的代码试图做什么感到非常困惑

到目前为止,“SendEmailOnAuthenticationFailed”尚未对外公开。我想做的是(我刚刚添加了IsAuthenticated)在“IsAuthenticated”中,当身份验证失败时,我希望发送一封电子邮件,而不必到处编写相同的事件处理程序

[UPDATE2]: 我意识到没有必要公开“AuthenticationFailed”。 我将尽可能地关闭该类,而不公开事件

为什么我们不能将多个答案标记为“答案”

[UPDATE3]:最终输出:下面是我决定如何实现的

public class Authenticator
{
    private readonly IEmailResponder _EmailResponder;

    public Authenticator(IEmailResponder emailResponder)
    {
        _EmailResponder = emailResponder;
    }

    public void IsAuthenticated()
    {
        // Some logic...
        // ...

        // Woops authentication failed
        SendEmailForAuthenticationFailure();
    }

    private void SendEmailForAuthenticationFailure()
    {
        _EmailResponder.SendEmail(...);
    }
}

倾听自己的事件是不寻常的;这种逻辑通常可以进入OnAuthenticationFailed方法。也就是说,我对您的代码试图做什么感到非常困惑,这使得回答有点困难


我怀疑它是否适用,但另外请注意,如果此代码是高度线程化的(大多数不是),您可能需要考虑一些微妙的问题(在谈论您自己的事件时)。

我想我第一次误解了您的问题。。。我说你想要一种可选的方式来做这件事对吗?就我个人而言,我怀疑我会在构造函数中选择:

public class Authenticator
{
    public event EventHandler AuthenticationFailed = delegate { };

    public Authenticator(bool sendEmailOnFailure)
    {
         if (sendEmailOnFailure)
         {
             // No need for the no-op delegate any more, so just replace it.
             AuthenticationFailed = EmailSender;
         }
    }
}

或者,将“电子邮件发送”功能从“身份验证”功能中分离出来,以便更好地分离关注点,并允许调用方使用电子邮件处理程序进行订阅(如果他们愿意)。这可能是一个更简洁的解决方案。

第一个问题的答案是它是可以接受的。对于你的后续行动,答案是视情况而定。第一种方法将电子邮件过程内部化。如果您选择这样做,请确保您正在注入电子邮件逻辑。如果选择后者,则允许您注入行为。但是,如果您使用第二个名称,我建议您更改名称,因为它是电子邮件、MQ还是TiddlyLink并不重要。事实上,第二种方法其实并不需要,因为它们可以直接订阅事件

如果您关心解耦,那么需要考虑Authenticator类的单一职责。应该是认证,而不是发送电子邮件。试试这个:

public class Authenticator
{
    public event EventHandler AuthenticationFailed = delegate { };

    protected virtual void OnAuthenticationFailed()
    {
        AuthenticationFailed(this, EventArgs.Empty);
    }
}
现在,使用验证器:

AuthenticationEmailResponder responder = new AuthenticationEmailResponder(emailAddress, emailServer);
objAuthenticator.AuthenticationFailed += responder.SendFailureMessage;

不,他们不能那样做。AuthenticationFailed是一个事件-它不能从类内的任何位置分配(在类中,相同的名称实际上指的是字段)。“如果您选择这样做,请确保您正在注入电子邮件逻辑”->是的,我实际上是通过构造函数注入emailer对象,上面的代码只是我在一分钟内组装的一个演示代码。这很好。如果您的业务用户希望在电子邮件之上添加其他通知方法,那么您仍然面临耦合问题。最好使用一个比电子邮件更通用的术语。无论这种做法是否可以接受,我决定现在不公开这个事件。它不见了。不需要保留死代码。谢谢。事实上,我是在问听它自己的对象的事件是否是一种可接受的做法,或者不是,甚至是通常的做法。如果是的话,我不知道如何向外界公开自我事件注册。