2

IOCで流暢な方法で使用できるSystem.Net.Mailラッパーを作成する必要があります。

アイデアは、次のように使用される2つのクラス、メーラーとメールを持つことです。

IMailer mailer = new Mailer();
IMail mail = new Mail()
  .Attach("Photo", fileData, "image/jpg")
  .Body("This is the photo I forgot to send")
  .From("from@xyz.com")
  .Subject("The missing photo")
  .To("to@xyz.com");
mailer.New(mail).Send();

または、次のような完全に流暢な方法で:

new Mailer()
  .New()
  .Attach("Photo", fileData, "image/jpg")
  .Body("This is the photo I forgot to send")
  .From("from@xyz.com")
  .Subject("The missing photo")
  .To("to@xyz.com")
  .Done()
  .Send();

私はほとんどの仕事をしましたが、処分に問題があります。メーラークラス:

  public interface IMailer : IDisposable {
    IMailer New(IMail mail);
    IMail New();
    void Cancel();
    void Send();
    void SendAsync(SendCompletedEventHandler callback, Object token = null);
  } // IMailer

  public class Mailer : IMailer {
    private SmtpClient _client;
    private IMail _mail;

    public Mailer() {
      _client = new SmtpClient();
    } // Mailer

    public IMailer New(IMail mail) {
      _mail = mail;
      return this;
    } // New

    public IMail New() {
      _mail = new Mail(this);
      return _mail;
    } // New

    public void Cancel() {
      _client.SendAsyncCancel();
    } // Cancel

    public void Send() {
      Send(null, null);
    } // Send

    public void SendAsync(SendCompletedEventHandler callback, Object token = null) {
      Send(callback, token);
    } // SendAsync

    private void Send(SendCompletedEventHandler callback = null, Object token = null) {

      using (MailMessage message = new MailMessage()) {
        message.From = new MailAddress(_mail.Data.From);
        message.Subject = _mail.Data.Subject;
        _mail.Data.To.ForEach(x => message.To.Add(new MailAddress(x)));
        message.Body = _mail.Data.Text;

        _mail.Data.Attachments.ForEach(x => { message.Attachments.Add(new Attachment(new MemoryStream(x.Value.Item2), x.Key, x.Value.Item1)); });

        if (callback == null)
          _client.Send(message);
        else {
          _client.SendCompleted += callback;
          _client.SendAsync(message, token);
        }

      };

    } // Send

    public void Dispose() {
      Dispose(true);
    } // Dispose

    protected virtual void Dispose(Boolean disposing) {
      if (disposing) {
        if (_client != null)
          _client.Dispose();
      }
    } // Dispose

  } // Mailer

また、メールデータを含み、メールを作成するメールクラスは次のとおりです。

  public interface IMail {
    MailData Data { get; }
    IMail Attach(String name, Byte[] file, String mime);
    IMail Body(String text);
    IMail From(String contact);
    IMail Subject(String subject);
    IMail To(String contact);
    IMailer Done();
  } // IMail

  public class Mail : IMail {
    private IMailer _mailer;
    public MailData Data { get; private set; }

    public Mail() {
      Data = new MailData();    
    } // Mail

    public Mail(IMailer mailer) {
      Data = new MailData();
      _mailer = mailer;      
    } // Mail

    public IMail Attach(String name, Byte[] file, String mime) {
      Tuple<String, Byte[]> attachment;
      if (!Data.Attachments.TryGetValue(name, out attachment))
        Data.Attachments.Add(name, new Tuple<String, Byte[]>(mime, file));
      return this;
    } // Attach

    public IMail Body(String text) {
      Data.Text = text;
      return this;
    } // Body

    public IMail From(String contact) {
      Data.From = contact;
      return this;
    } // From

    public IMail Subject(String subject) {
      Data.Subject = subject;
      return this;
    } // Subject

    public IMail To(String contact) {
      Data.To.Add(contact);
      return this;
    } // To

    public IMailer Done() {
      return _mailer;
    } // Done

  } // Mail  

  public class MailData {

    public Dictionary<String, Tuple<String, Byte[]>> Attachments { get; set; }
    public String From { get; set; }
    public String Subject { get; set; }
    public String Text { get; set; }
    public HashSet<String> To { get; set; }

    public MailData() {
      Attachments = new Dictionary<String, Tuple<String, Byte[]>>();
      To = new HashSet<String>();
    } // MailData

  } // MailData

メーラーは、電子メールの送信直後に破棄されるMailMessageを使用します。

メーラーを破棄すると、SMTPクライアントも破棄されます...

ただし、メール自体を破棄する方法がわかりません。

これは、MailDataディクショナリ内のすべての添付ファイルをクリアするために重要です。

私は2つの方法でそれを行うことができるはずです:

IMail mail = new Mail()
  .Attach("Photo", fileData, "image/jpg")
  // Define other properties of mail
// Send mail using mailer
mail.Dispose(); // Dispose mail

または完全に流暢な場合:

mailer
  .New()
  .Attach("Photo", fileData, "image/jpg")
  // Other properties of mail
  .Done()
  .Send()
  .Dispose();

これにより、メーラーとそのメールが破棄されます...または:

mailer
  .New()
  .Attach("Photo", fileData, "image/jpg")
  // Other properties of mail
  .Done()
  .Send()
  .Clear;

これにより、メーラーに関連付けられているメールは破棄されますが、メーラーには破棄されないため、同じメーラーで別のメールを送信できます。

または、提案する可能性のあるその他の構成。

最善の方法がわかりません...

どんなアドバイスでも大歓迎です。

ありがとうございました、

ミゲル

注:IOCを使用する場合、サービスにIMailerを挿入します...

4

2 に答える 2

2

私があなたのコードで見る唯一の管理されていないリソースはSmtpClientです。したがって、IMailerのみを破棄する必要があります。MailとMailDataはすべて管理されているため、破棄する必要はありません。したがって、mailer.Dispose()を呼び出すだけで、それだけです。

(ところで、usingブロック内でMailerを使用することをお勧めします。)

編集:あなたがSendAsnycも使用していることに気づきました。これにより、処理が少し難しくなります。非同期で送信する場合は、コールバックでdisposeを呼び出す必要があります。したがって、プライベートSendメソッドもMailMessageオブジェクトを(usingブロックで)破棄するため問題があるように見えますが、SendAsyncはそれを必要とする可能性があります。

参照:

于 2013-03-25T12:46:42.447 に答える
0

クラスを1回限りで作成します。つまり、1つのインスタンスが1つの電子メールを送信し、それを破棄することができます。このようにして、Sendを呼び出すときに、IMailとIMailerの両方の実装を適切に破棄できます。IMailerを要求したときに、常に新しい一意のインスタンスを返すようにIoCを構成できます。

この設計には、インターフェースを使用する人々がそれを処分することを忘れないという追加の利点があります。

あるいは、ブロックパターンを使用して標準に固執することもできますが、コンテナから渡されたものを処分することは私にはいつも奇妙に思えます。

于 2013-03-25T12:59:25.540 に答える