2017-08-09 12 views
-1

メールの送信を処理する別のクラスを作成しました。私はそれを設計するために依存性注入を使っています。今、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

あなたが意味することを記述できますか?それを実装しているクラスでイベントを実装する方法を混乱させています。インターフェイスでこのイベントを言及せずに、私は注入クラスでそれをキャッチすることはできません*あなたが実装をイベントを管理する必要はないと言っている? – Nico

+0

私はそれを管理したいです。インプリメンテーションでは、実装されていないと言われる部分で、代理イベントをどのように配置して、注入されたクラスをキャッチできるかを示します。 – 3not3

+0

イベントを実装するのと同じ方法で、イベントをインターフェイスに実装します。投稿したコードに基づいて、Visual Studioの "明示的にインターフェイスを実装する"オプションを使用したように見えます。これは、イベント宣言の明示的なフォームを 'add()'と 'remove()'メソッド。イベントの特別な処理を望まないなら、それをしないでください。イベントをインターフェイスで宣言するだけです。つまり、 'publicイベントSendCompletedEventHandler OnEmailSendComplete;'を呼び出すと、コンパイラは 'add()'と 'remove()'メソッドをあなたに代入させます。 –

答えて

2

コードには、2つの異なる非同期パターンが含まれています。古い数字はevent-based asynchronous patternで、新しい数字はtask-based asynchronous patternです。特に、SmtpClient.SendCompletedSmtpClient.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); 
    } 
} 

が、それは抽象化ではありません。 ;)

+0

実際には、私はそれ以上のものを持っています。ちょうどそれをたくさんのコードで氾濫させたくないので、疑いの余地がある部分を投稿しました。私はSendAsync()とSendMailAsync()を混同しました。しかし、私はあなたが+1したこれら2つのパターンを知る必要があります。 – 3not3

関連する問題