我创建了一个单独的类来处理邮件发送。为了使其免于未来的变化,我使用依赖注入来设计它。现在,当我尝试使用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;
}
}
我尝试尽可能少地编写代码以解释我的困惑,因此这段代码在真实场景中不起作用,但具有我相信的结构。如果我夸大了,请告诉我。我感谢任何帮助。
答案 0 :(得分:2)
您的代码将两种不同的异步模式混为一谈:较旧的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);
}
}
最后提醒一下,如果您的抽象只有一个实现,那么它不是抽象。 ;)