8

私はDI/IoCコンテナOpenNETCF.IoCに取り組んでいます。コンテナコレクション内のIDisposableアイテムのライフサイクル管理のいくつかのフォームを追加する(合理的な)機能リクエストがあります。DI:IDisposableオブジェクトの寿命を処理する

私の現在の考えは、オブジェクトが処分されているかどうかを調べることができず、処分されたときにイベントを受け取ることができないため、オブジェクトのラッパー開発者はフレームワークの管理を望んでいます。うまく

public TTypeToBuild AddNew<TTypeToBuild>() { ... } 

私は新しいメソッドを追加して検討している(:今AddNewの(単純化のために、我々は唯一のオーバーロードがありますし、何の追加がないと仮定します)を追加することができるオブジェクト

それらのグループが、あなたは)画像を取得します:

public class DisposableWrappedObject<T> 
    where T : class, IDisposable 
{ 
    public bool Disposed { get; private set; } 
    public T Instance { get; private set; } 

    internal event EventHandler<GenericEventArgs<IDisposable>> Disposing; 

    internal DisposableWrappedObject(T disposableObject) 
    { 
     if (disposableObject == null) throw new ArgumentNullException(); 

     Instance = disposableObject; 
    } 

    ~DisposableWrappedObject() 
    { 
     Dispose(false); 
    } 

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

    protected virtual void Dispose(bool disposing) 
    { 
     lock(this) 
     { 
      if(Disposed) return; 

      EventHandler<GenericEventArgs<IDisposable>> handler = Disposing; 
      if(handler != null) 
      { 
       Disposing(this, new GenericEventArgs<IDisposable>(Instance)); 
      } 

      Instance.Dispose(); 

      Disposed = true; 
     } 
    } 
} 
:DisposableWrappedObjectはこのようになります

public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>() 
    where TTypeToBuild : class, IDisposable 
{ 
    ... 
} 

AddNewDIsposableでアイテムがコンテナに追加されると、イベントハンドラが追加され、(ラッパーを介して)Disposedになると、フレームワークはそれを基になるコレクションから削除します。

これは実際に実装されており、単体テストに合格していますが、どこが壊れているのか、消費者にとってより「フレンドリー」になるかについての意見を探しています。

EDIT 1

質問は廃棄イベントの使用方法にありましたので、ここでは(何が重要かにトリミング)いくつかのコードがあります:

private object AddNew(Type typeToBuild, string id, bool wrapDisposables) 
{ 
    .... 

    object instance = ObjectFactory.CreateObject(typeToBuild, m_root); 

    if ((wrapDisposables) && (instance is IDisposable)) 
    { 
     DisposableWrappedObject<IDisposable> dispInstance = new 
       DisposableWrappedObject<IDisposable>(instance as IDisposable); 
     dispInstance.Disposing += new 
       EventHandler<GenericEventArgs<IDisposable>>(DisposableItemHandler); 
     Add(dispInstance as TItem, id, expectNullId); 
     instance = dispInstance; 
    } 

    .... 

    return instance; 
} 

private void DisposableItemHandler(object sender, GenericEventArgs<IDisposable> e) 
{ 
    var key = m_items.FirstOrDefault(i => i.Value == sender).Key; 
    if(key == null) return; 
    m_items.Remove(key); 
} 
+0

は、我々は追加されている特定の機能の充実説明を取得することはできますか?人々がこれを望んでいるユースケースは何ですか?(IoCフレームワーク)またはエンドユーザーとしてのあなたのためのイベントハンドラですか?等。 – Quibblesome

+0

ユースケースは、自動ライフサイクル管理を追加することです。 IDisposableアイテムをコレクションに追加し、後でDisposeを呼び出すと、コンテナがオブジェクトのルートを保持するため、実際には決してクリーンアップされません。そのアイデアは、あなたがコレクションに戻ってそれを見つけ出す必要なく、オブジェクトに対してDisposeを呼び出すことができ、コンテナコレクションからの削除を自動的に引き起こすことができるということです。 イベントは、フレームワークによって純粋に内部的に使用されます(外部で使用されないように内部としてマークさえさえあります)、ハンドラはコレクションからそれを削除します。 – ctacke

+0

わかりやすくするために、イベント処理を追加するための質問を更新しました。 – ctacke

答えて

3

たぶん私は何かが欠けているんだけど、なぜ新しいメソッドをAPIに追加するのですか?オブジェクトがコンテナに追加されるときに、IDisposableであるかどうかをチェックし、適切な場合はそれを適切に処理するためにキャストすることができます。

デストラクタが必要かどうかも疑問です。コンテナがIDisposable(Unityのように)であると仮定すると、Basic Dispose Patternを実装してGCオーバーヘッドを大幅に削減できます。

も適用することができるいくつかの質問:

+0

ああ、でもキャスト時には? IDisposableでコンテナに入れなければならないことはわかっていますが、AddNew <>メソッドは入力タイプを返さなければならないので、コンテナを返すことはできません。 APIが望むようにオブジェクトを直接返すと、ラップされたことはわかりませんし、コンテナではなくインスタンスに対してDisposeを呼び出すだけで、GC化されないDisposedオブジェクトを保持する問題があります。 – ctacke

+5

@ctacke:消費者がIoCで遊ぶときに従わなければならない規則がいくつかあります:DIコンテナに*作成*オブジェクトの責任を渡すときは、インスタンスの破棄*を含む*すべてのライフタイムマネジメントを渡す必要があります。したがって、それらのインスタンスが複数のコンシューマ間で共有される可能性があるため、注入された依存関係を早期に処理すると、消費者側でエラーになります。私はあなたのAPIを過度に複雑にする必要はないと思うが、それは間違っている使用法を守るためだ。 –

関連する問題