繁体   English   中英

如果接口中有事件,如何实现事件,以及如何在依赖注入中使用事件

[英]How to implement an event if I have event in interface, also how I can use it in dependency Injection

我创建了一个单独的类来处理邮件发送。 为了使它免于将来的更改,我使用了依赖注入来设计它。 现在,当我尝试使用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;
    }
}

我尝试使用尽可能少的代码来解释我的困惑,因此该代码无法在实际情况下使用,但具有我认为的结构。 如果我过分夸张,请告诉我。 感谢您的帮助。

您的代码正在合并两种不同的异步模式:旧的基于事件的异步模式和新的基于任务的异步模式 特别是, 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);   
  }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM