【问题标题】:How to implement an event if I have event in interface, also how I can use it in dependency Injection如果接口中有事件,如何实现事件,以及如何在依赖注入中使用它
【发布时间】:2018-01-17 23:21:28
【问题描述】:

我创建了一个单独的类来处理邮件发送。为了让它免于未来的变化,我使用了依赖注入来设计它。现在,当我尝试使用SendMessageAsync() 方法时,我想检查 SendMailCompleted 事件以查看发送失败/成功的消息状态。我很困惑我应该如何在实现它的类中实现事件。如果不在界面中提及此事件,我将无法在注入类中捕获它。任何人都可以建议如何解决这个问题?我的界面如下所示

public interface IMailing
{
    string Host { get; set; }
    int Port { get; set; }
    Task SendMailAsync(string toAddress, string subject, string body);

    event SendCompletedEventHandler OnEmailSendComplete;
}

实现接口的类如下-

public class Mailing : IMailing
{
    private SmtpClient client = new SmtpClient();
    MailMessage mm = null;

    public string Host{ get;  set; }
    public int Port { get; set; }

// do i need this? without event being in the interface I would have had this //two following lines to manually raise the event 
    public event SendCompletedEventHandler OnEmailSendComplete;

    public delegate void SendCompletedEventHandler(object source, AsyncCompletedEventArgs e);



// following lines were generated from the vs2017 IDE
// how do I use it when actual Send mail completed event fires?
    event System.Net.Mail.SendCompletedEventHandler IMailing.OnEmailSendComplete
    {
        add
        {
            throw new NotImplementedException();
        }

        remove
        {
            throw new NotImplementedException();
        }
    }

    public async Task SendMailAsync(string toAddress, string subject, string body)
    {            
        mm = new MailMessage(User, toAddress, subject, body);
        client.SendCompleted += Client_SendCompleted;
        await client.SendMailAsync(mm).ConfigureAwait(false);
    }

    private void Client_SendCompleted(object sender, AsyncCompletedEventArgs e)
    {
        OnEmailSendComplete?.Invoke(sender, e);
    }
}

现在,注入类使用构造函数注入,如下所示-

public class MailingInjection
{
    IMailing mailing = null;

    private MailingInjection()
    { }
    public MailingInjection(IMailing imail)
    {
        mailing = imail;
    }              

    public async Task SenMailAsync(string to, string subject, string body)
    {
        mailing.OnEmailSendComplete += EmailSendCompleted;
        await mailing.SendMailAsync(to, subject,body).ConfigureAwait(false);   
    }

    private void EmailSendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        mailing.OnEmailSendComplete -= EmailSendCompleted;
    }
}

我尝试使用尽可能少的代码来解释我的困惑,因此这段代码在实际场景中不起作用,但具有我相信的结构。如果我夸大了,请告诉我。我很感激任何帮助。

【问题讨论】:

  • 你能描述一下你的意思吗我很困惑我应该如何在实现它的类中实现事件。如果不在接口中提及此事件,我将无法在注入类中捕获它是说您不希望实现来管理事件?
  • 我确实想管理它;在实现中,它说“未实现”的部分我如何放置我的委托事件来引发,以便我可以在注入的类中捕获。
  • 您在接口中实现事件的方式与实现任何事件的方式相同。根据您发布的代码,您似乎使用了 Visual Studio 中的“显式实现接口”选项,它为您提供了(惊喜!)事件声明的显式形式,以及 add()remove() 方法。如果您不想对事件进行特殊处理,请不要这样做。只需在接口中声明事件,即public event SendCompletedEventHandler OnEmailSendComplete;,然后让编译器为您填写add()remove() 方法。
  • 我只是不明白为什么人们会投反对票,在 stackoverflow 中询问/发布内容需要花费很多时间才能赢得声誉。如果我知道我要做什么,我就不会来这里……人们需要了解这个事实。

标签: c# dependency-injection interface


【解决方案1】:

您的代码将两种不同的异步模式混为一谈:旧的event-based asynchronous pattern 和新的task-based asynchronous pattern。特别是,SmtpClient.SendCompleted 仅与SmtpClient.SendAsync 一起使用。你的代码没有使用SendAsync,所以它不需要SendCompleted。它可以只使用SmtpClient.SendMailAsync

public interface IMailing
{
  string Host { get; set; }
  int Port { get; set; }
  Task SendMailAsync(string toAddress, string subject, string body);
  // No event necessary.
}

public class Mailing : IMailing
{
  private SmtpClient client = new SmtpClient();
  MailMessage mm = null;

  public string Host{ get;  set; }
  public int Port { get; set; }

  public async Task SendMailAsync(string toAddress, string subject, string body)
  {            
    mm = new MailMessage(User, toAddress, subject, body);
    await client.SendMailAsync(mm).ConfigureAwait(false);
  }
}

用法:

public class MailingInjection
{
  ...

  public async Task SenMailAsync(string to, string subject, string body)
  {
    await mailing.SendMailAsync(to, subject,body).ConfigureAwait(false);   
  }
}

最后提醒一下,如果您的抽象只有一个实现,那么它就不是抽象。 ;)

【讨论】:

  • 其实我还有更多,只是不想用大量代码淹没它,所以只发布了我有疑问的部分。我将 SendAsync() 与 SendMailAsync() 混淆了。但我需要知道你提到的这两种模式 +1。
猜你喜欢
  • 2018-09-27
  • 2021-03-23
  • 2012-12-02
  • 2011-05-06
  • 2020-08-30
  • 2023-02-21
  • 2021-11-28
  • 2022-12-15
  • 1970-01-01
相关资源
最近更新 更多