2017-04-05 4 views
1

私は本当にいくつかの言葉で、私がより詳細に必要なものを記述することができるタイトルを考えることができませんでした。 最終的には、メッセージをAzure Service Busに送信するためのカスタム実装を使用しています。この実装はNuGetパッケージにラップされています。QAの自動化に必要なメッセージをデータベースに保存するロジックを追加しようとしています。ここで難しいのは、NuGetパッケージを変更せずに、すべての追加ロジックを "ラップ"したいということです。 パッケージ自体にはsealedクラスとinternalインターフェイスがたくさんありますが、私は必要なチェーンを抽出することができたと思います。身分証明書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を信用しないことを学んだことがあります。誰かが抽象クラスで、なぜデストラクタの目的であるものを私に説明できる場合、私は本当に感謝この絵を持っ

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(); 
    } 
} 

だから最後に私は抽象MessageBusBaseを継承sealedクラスを持っていますそれが必要です。私は、デストラクタをいつ使うべきか、なぜそれを使うべきかについて読んでいるところですが、私が達する結論は、実際にはそれを必要としない可能性が最も高いということです。しかし、AzureMessageBusではAzureへの実際の呼び出しであり、メソッドで使用しているIMessageインターフェイスもGoogle.ProtocolBuffersです。これは答えかもしれませんが、今私はちょうど推測しています。これは私の質問の最初の部分です。

2番目の部分は私の追加ロジックを追加しています。私がやったこと、新しいクラス作成することによって:私は、元の実装を呼んでいる私の新しいクラスから

return (IMessageBus) new AzureMessageBus(..) 

だから、基本的には、すべてです:this.messageFactory.CreateMessageBus();はそうのようなAzureMessageBusのインスタンスを返します

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 
} 

を私は私の新しいクラスAzureMessageBusWithLoggingIMessageBusを実装する必要があるためAzureMessageBusからの方法は、私は追加することを強制しています:

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

しかし、本当に何かをする必要がある場合、私は実際に何を入れるかわからない。また、私が実際にGCの実装を必要としている理由(私の視点から見ると複雑なもの)と、新しいクラスの処分が既存のAzureMessageBusに影響を与える可能性がある理由について、説明していただきたいと思います。私の新しいクラス。

+0

'MessageBusBase'は、継承されたクラスにDisposeロジックを実装させる抽象的な' Dispose'メソッドを定義しています。実装に何も配置しない場合は、空のままにしてください。なぜあなたは例外をスローしますか(特に、このコードはファイナライザによって実行されると仮定します)。 –

+0

@YeldarKurmangaliyev私はこのデザインでちょっと混乱しています。これは主に新しいものなので、今はあまりにも多くの時間を費やして「GC」を考えることはありません。だからこそ私はこの質問をしていますが、このデザインが何を目指しているのか(もしあれば)、そしてそれをこのように実装することで達成するものが何であるかはわかりません。だから、なぜ例外があるのか​​知りたい。そして、Disposeの答えに感謝します。私はまたそれを空のままにすることに傾いている。 – Leron

答えて

2
  1. 解放する必要のある直接のアンマネージリソースを保持していないため、デストラクタは必要ありません。IDisposableオブジェクトをラップするだけの場合は、デストラクタなしでDisposeを実装してください。それらのオブジェクトが管理されていないリソースを保持している場合、それらは独自のデストラクタを持ちます。

  2. IMessageBusには既にIDisposableが含まれているため、MessageBusBase : IMessageBus, IDisposableを実行する必要はありません。もしあなたがそれを行うならば、害はありません。

  3. あなたのAzureMessageBusWithLoggingにあなたは別のIMessageBus messageBusをラップします。だからDispose - それを処分するmessageBus。一般的にはそう

:あなたには、いくつかの使い捨てのオブジェクトをラップする場合 - あなたのクラスはまた、あなたがAzureMessageBus.Disposeで行うと同じように、IDisposableを実装し、それ自身のDisposeにすべてのそれらの包みのオブジェクトを配置する必要があります。

+0

私は、あなたのクラスでもIDisposableを実装し、それらのラップされたオブジェクトをすべて自分自身のDisposeに配置する必要があります。ですから、正しく理解したら 'Dispose()'メソッドで 'this.messageBus.Dispose()'のようなものを提案しますか? – Leron

+0

そうです。 AzureMessageBus(送信者を処分する)ですでに同じことをしているので、別のクラスの同様のケースの混乱を引き起こした原因は不明です。 – Evk