2013-03-25 81 views
2

我需要創建一個System.Net.Mail包裝器,我可以使用IOC和Fluent方式。創建郵件程序和郵件類。需要關於處置的建議

的想法是將有兩班,梅勒和郵件,使用方法如下:

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

或者全流利的方式是這樣的:

new Mailer() 
    .New() 
    .Attach("Photo", fileData, "image/jpg") 
    .Body("This is the photo I forgot to send") 
    .From("[email protected]") 
    .Subject("The missing photo") 
    .To("[email protected]") 
    .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字典中的所有附件文件非常重要。

我應該能夠做到這一點有兩種方式:

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; 

這將處理與郵件相關的郵件,但不是郵件程序,所以我可以發送另一封郵件與相同的郵件河

或者您可能會建議的任何其他配置。

我不確定最好的方法去...

任何建議是值得歡迎的。

謝謝你,

米格爾

注意:使用國際奧委會的時候我會注入IMailer在我服務的......

回答

2

唯一的非託管資源我在你的代碼看到的是SmtpClient。所以只有IMailer應該被處置。 Mail和MailData都是託管的,所以不需要處理它們。所以你只需要調用mailer.Dispose()就可以了。

(順便說一下它是使用梅勒using塊內是個好主意。)

編輯: 我剛剛注意到,你還可以使用SendAsnyc這使得配置有點麻煩。異步發送時,應該在回調中調用dispose。因此,您的私人發送方法似乎也有問題,因爲它會部署MailMessage對象(使用使用塊),但SendAsync可能仍然需要它。

參見:

+0

感謝您提供有關SmtpClient和Async的提示。關於在一個使用塊中使用郵件程序是有道理的,但是我使用StructureMap將郵件程序注入到我的服務中,因此SM將在這種情況下處理這個問題......如果我要在服務中創建郵件程序,那麼它對於將其包裹成使用...這是你的意思? – 2013-03-25 22:03:40

+0

我不知道StructureMap,但如果我認爲它與Unity相似(我熟悉),那麼您有2個選項來獲取對象實例:通過注入(到ctor或屬性)或通過解析它直接(如:var mailer = ObjectFactory.GetInstance ())。在後一種情況下,您可以使用使用塊。在前一種情況下(注入),我不確定正確的方法,因爲您不僅要在完成對象時處理對象,還要確保即使發生異常時也能處理該對象。 – Vizu 2013-03-26 08:38:04

+0

另一個問題:請注意,我正在使用Stream填充MailMessage上的附件。這是因爲它System.Net.Mail附件不接受Byte [],這是我在我的郵件對象。我需要處理Streams嗎?我不知道是否以及如何......他們需要在場,直到發送消息。 – 2013-03-26 12:59:08

0

我想創建班級爲一次性的;也就是說,一個實例可以發送一封電子郵件,然後將其丟棄。通過這種方式,您可以在調用Send時正確處理IMail和IMailer實現。您可以配置您的IoC,以便在請求IMailer時始終返回一個新的唯一實例。

此設計還有一個額外的好處,即使用您的界面的人不會忘記處置它。或者,你可以堅持使用塊模式的標準,儘管處理一個容器發出的東西對我來說似乎很奇怪。

+0

但是不是創建一個SMPT客戶端昂貴?不應該有一個好主意,由Thread創建一個郵件程序? – 2013-03-26 12:57:34

+0

這取決於;你可以做到這一點,但你仍然需要確保它的處理正確,所以你必須知道線程何時關閉等。除非創建SMTP客戶端的性能損失正在終止您的應用程序,否則我會選擇確保正確處理它的選項,因爲我認爲不當處置可能會破壞您的應用程序,然後創建客戶端的「昂貴」。 – Andy 2013-03-26 21:42:31

相關問題