2017-04-05 38 views
1

我真的無法想象一個標題,可以用幾個詞,描述我需要更多的細節。 最終的想法是我使用自定義實現來發送消息到Azure Service Bus。這個實現被封裝在一個NuGet包中,我試圖添加一些額外的邏輯,將消息保存到QA自動化目的所需的數據庫中。這裏棘手的部分是,我希望NuGet包保持不變,所有額外的邏輯要「包裹」它。 所以包本身有很多sealed類和internal接口,但我想我已經設法提取我需要的鏈。 首先我有這個接口是從所有的類用於發佈消息到服務總線:Impementing IDisposable

public interface IMessageBus : IDisposable 
{ 
    bool Send(IMessage command); 

    bool Send(IMessage command, string trackingId); 

    Task<bool> SendAsync(IMessage command); 

    Task<bool> SendAsync(IMessage command, string trackingId); 

    bool Publish(IMessage eventObj); 

    bool Publish(IMessage eventObj, string trackingId); 

    Task<bool> PublishAsync(IMessage eventObj); 

    Task<bool> PublishAsync(IMessage eventObj, string trackingId); 
} 

它是包的一部分,但是是少數public接口之一。然後我有一個抽象類實現這個接口:

public abstract class MessageBusBase : IMessageBus, IDisposable 
{ 
    ~MessageBusBase() 
    { 
     this.Dispose(false); 
    } 

    #region Interface 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize((object)this); 
    } 

    protected abstract bool SendMessage(IMessage payload, string trackingId); 

    protected abstract Task<bool> SendMessageAsync(IMessage payload, string trackingId); 

    protected abstract void Dispose(bool disposing); 
} 

從這裏我開始鬆開實現背後的想法。由於IMessageBus已經實現了IDisposable爲什麼抽象類應該再次實現它? Resharper也標記爲不需要,但我已經學會不要每次都信任Resharper

所以在最後我有sealed類繼承抽象MessageBusBase

public sealed class AzureMessageBus : MessageBusBase 
{ 
    private bool isDisposed; 

    #region MessageBusBase 

    protected override void Dispose(bool disposing) 
    { 
     if (!disposing) 
      return; 
     this.isDisposed = true; 
     foreach (IDisposable disposable in (IEnumerable<ISender>)this.senders.Values) 
      disposable.Dispose(); 
    } 
} 

有了這個圖片我真的很感激,如果有人可以給我解釋一下什麼是析構函數的抽象類,爲什麼目的我們需要。我花了一些時間閱讀關於什麼時候和爲什麼應該使用析構函數,以及我已經達到的結論是,實際上我們很可能不需要它。然而在AzureMessageBusAzure的實際調用,我們在SendMessageAsync方法中使用的IMessage接口的實際調用是從Google.ProtocolBuffers開始,也許這可能是答案,但現在我只是猜測。所以這是我的問題的第一部分。

第二部分是添加我的附加邏輯。我這樣做,通過創建一個新的類:

public class AzureMessageBusWithLogging : IMessageBus 
{ 
    private IMessageBus messageBus; 

    private IMessagingFactory messageFactory; 

    public AzureMessageBusWithLogging(IMessagingFactory msgFactory) 
    { 
     this.messageFactory = msgFactory; 

     if (messageFactory != null) 
     { 
      this.messageBus = this.messageFactory.CreateMessageBus(); 
     } 
    } 

    public Task<bool> SendAsync(IMessage command, string trackingId) 
    { 
     //Place for my additional logic 
     return ((AzureMessageBus)messageBus).SendAsync(command, trackingId); 
    } 

    public void Dispose() 
    { 
     throw new NotImplementedException(); 
    } 

    #region IMessageBus 
} 

this.messageFactory.CreateMessageBus();返回像這樣的AzureMessageBus一個實例:

return (IMessageBus) new AzureMessageBus(..) 

所以基本上這一切,從我的新類我打電話的原來的實現從AzureMessageBus的方法,但因爲我需要在我的新類AzureMessageBusWithLogging實施IMessageBus我不得不補充:

public void Dispose() 
    { 
     throw new NotImplementedException(); 
    } 

但是我真的不知道該在裏面放什麼,如果我真的需要做點什麼。同時我也會很感激解釋爲什麼我們需要這個(從我的觀點來看很複雜)實現GC以及如何以任何方式在我的新類中處置可能會影響現有的AzureMessageBus,因爲我使用它的實例我的新班級。

+0

'MessageBusBase'只是定義了一個抽象的Dispose方法,讓繼承類實現Dispose邏輯。如果在你的實現中沒有任何東西需要處理,那就把它留空。爲什麼拋出一個異常(特別是假設這個代碼將由finalizer運行)。 –

+0

@YeldarKurmangaliyev我對這個設計有些困惑,主要是因爲它是新東西,直到現在我從不花太多時間思考'GC'。這就是爲什麼我問這個問題,不確定這個設計的目標是什麼(如果有的話)以及我們通過這種方式實現的目標。所以我也想知道爲什麼是例外。並感謝'Dispose'答案。我也傾向於將它留空。 – Leron

回答

2
  1. 你不需要析構函數,因爲你不抱你需要釋放任何直接的非託管資源。如果你只包裝了一些IDisposable對象 - 只需實現Dispose而沒有析構函數。如果這些對象確實擁有一些非託管資源 - 它們將擁有自己的析構函數。

  2. 您不需要做MessageBusBase : IMessageBus, IDisposable,因爲IMessageBus已經包含IDisposable。雖然如果你這樣做 - 沒有傷害

  3. 在你的AzureMessageBusWithLogging你換一個IMessageBus messageBus。所以在Dispose - 處置那messageBus

一般

所以:如果你換一些一次性的對象 - 你的類也應該實現IDisposable並在它自己的Dispose處理所有這些包裹的物體,就像你在做AzureMessageBus.Dispose

+0

我明白了,對此並不確定 - 「你的類還應該實現IDisposable並將所有這些包裝對象置於其自己的Dispose中。所以如果我正確理解你,你在'Dispose()'方法中提出了'this.messageBus.Dispose()'這樣的東西。 – Leron

+0

沒錯。您已經在AzureMessageBus中執行相同的操作(處理髮件人),因此不確定是什麼導致了另一個類中類似案例的混淆。 – Evk