2016-12-16 11 views
0

私はIDisposableを実装するサードパーティのオブジェクトを使っています。ユニットテストを "有能"にするために、私はラッパーを作ります。私はオブジェクトがIDisposableを実装していることを理解しています。私のラッパーはIDisposableも実装する必要があります。IDisposableの実装と使用

public interface IWrapper : IDisposable 
{ 
    void Complete(); 
} 

public class Wrapper : IWrapper 
{ 
    private readonly ThirdPartyLib lib; 

    public Wrapper() 
    { 
     lib = new ThirdPartyLib(); 
    } 

    public void Complete() 
    { 
     lib.Comlete(); 
    } 

    public void Dispose() 
    { 
     lib.Dispose(); 
    } 
} 

public class Processor : IProcessor 
{ 
    private readonly IWrapper wrapper; 
    public Processor(IWrapper wrapper) 
    { 
     this.wrapper = wrapper; 
    } 

    public void Process() 
    { 
     // do some work 
     using (wrapper) { 
      // do more work 
     } 
    } 
} 

と仮定プロセッサはそれとプロセスを使用しているいくつかのクラスに注入された()、我々は再びプロセスを()を呼び出す場合はラッパーにhappends何

  • を実行していますか? - ThirdPartyLib()はラッパーコンストラクターで一度だけ作成されたため、例外をスローしませんでした。
  • 参照がある限り、処分されませんか?
  • ラッパーは多分(開始と言う、新しい()ThirdPartyLibの「INGのが」ないコンストラクタではなく、別々の方法で実行するように構築する必要があります) - そのような:
public class Wrapper : IWrapper 
    { 
     private ThirdPartyLib lib; 

     public void Begin() 
     { 
      lib = new ThirdPartyLib(); 
     } 

     public void Complete() 
     { 
      lib.Comlete(); 
     } 

     public void Dispose() 
     { 
      lib.Dispose(); 
     } 
    } 

そして、それを使用して:

using (wrapper.Begin()) { 
+1

私はこれについて大きなイメージを持っていないと感じます。なぜ 'Processor'はコンストラクタに注入された' Wrapper'を処理するのですか?通常、私はあなたが 'Processor'が' Process(IWrapper wrapper) 'のようなメソッド呼び出しを持っていて、あなたがそのラッパーを処理できるようにすると期待していますが、呼び出し側が呼び出す必要があるそれを効果的に所有しているので、 'IWrapper'に' Dispose 'します。これが当てはまらない場合、私はおそらく 'IDisposable'を' IProcessor'に実装して、 'IWrapper'を処分するときだけ処分します。 –

+0

IProcessorにIDisposableを実装すると、(現在の設計で)IProcessorが処分されたときにWrapperを処分するだけで、usingステートメントのヒットにヒットしない場合は除きますか?これは、(親)IPプロセッサがIWrapperへの参照を保持しているからです - 私たちは "}"に処分するように言いました。 – BobSwanson

+0

それで、DIで初期化されたオブジェクトは、ほとんどの場合、他のオブジェクトによって使用されるシングルトンであるか、少なくとも他の何かがライフタイムを制御しています。 DIに依存するオブジェクトはオブジェクトを単に使用するだけで、オブジェクトを作成したものが何であっても後でそれをヌークする責任があります。 DIは〜のようです_ "ちょっとオブジェクトがほしい、他の誰かが私のためにそれを作成して削除することができます" _ – MickyD

答えて

2

をあなたが気にする権利です。 Process()を2回呼び出すと、例外が発生する可能性があります。 Process()をまったく呼び出さないと、オブジェクトは非表示のままになります。

代わりに行うべきことは簡単なルールはありません。複数のオプションがあり、あなたの質問にないコードの他の部分に依存します。

Processorが外部所有のWrapperへの参照を取得する場合は、そのラッパーを処分してはなりません。

Processorが構築時にWrapperの所有権を取得する場合は、そのラッパーを廃棄時に処分する必要があります。つまり、ProcessorにはIDisposableも実装する必要があります。

を要求時に新しいWrapperを作成するように変更することができ、Process()が完了するとそのラッパーを廃棄することができます。

Wrapperを変更してオンデマンドでThirdPartyLibを作成しても問題ありません。しかし、注意してください:wrapper.Begin(); wrapper.Begin();を呼び出すと、ThirdPartyLibは非表示になり、参照されなくなります。これが問題になるのを防ぐためにAPIをもう少し再構成する必要があります。それは実質的にWrapperThirdPartyLibFactoryにすることを意味します。

+0

あなたはどのように呼び出しを説明してください:wrapper.Begin(); wrapper.Begin(); 1つは未知のままにしておきますか? – BobSwanson

+0

@BobSwanson 'wrapper.Begin()'はサードパーティ製のlibを作成します。それをAと呼ぶことにしましょう。次にもう一度呼びます.2番目のサードパーティ製のlibを作成しました。これをBとしましょう。 Bを指し、何もAを指していない。 'wrapper.End()'を呼び出すと、Bを破棄する 'lib.Dispose()'が呼び出されますが、Aはまだ周囲にあります。 – Quantic

1

私はIWrapperをインスタンス化したものではなく、他のオブジェクトに注入することができないのか、それともそれが他のオブジェクトに注入されているのかわからないため、IWrapperを処分するべきではないと思います。その場合、Processorはラッパーでusingを使用しないでください。

IWrapperを処分するコードは、それがライフサイクルを知っているので、最初にインスタンス化したクラスに入れる必要があります。

関連する問題