ディ:IDisposable オブジェクトの寿命の処理
-
21-09-2019 - |
質問
それで私はDI/IoCコンテナに取り組んでいます OpenNETCF.IoC そして、コンテナ コレクション内の IDisposable アイテムに対して何らかの形式のライフサイクル管理を追加するという (合理的な) 機能リクエストがあります。
私の現在の考えは、オブジェクトが破棄されたかどうかを問い合わせることができず、破棄されたときのイベントを取得できないため、開発者が必要とするオブジェクトに対して何らかの形式のラッパーを作成する必要があるということです。管理するためのフレームワーク。
現時点では、AddNew を使用してオブジェクトを追加できます (わかりやすくするために、オーバーロードが 1 つだけあり、Add はないと仮定します)。
public TTypeToBuild AddNew<TTypeToBuild>() { ... }
私が検討しているのは、新しいメソッドを追加することです(それらのグループですが、全体像は理解できます)。
public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>()
where TTypeToBuild : class, IDisposable
{
...
}
DisposableWrappedObject は次のようになります。
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;
}
}
}
現在、AddNewDIsposable 経由でアイテムがコンテナに追加されると、イベントハンドラーも追加されるため、アイテムが (ラッパー経由で) 破棄されると、フレームワークによって基礎となるコレクションからアイテムが削除されます。
実際にこれを実装し、単体テストに合格していますが、これがどこで壊れる可能性があるか、または消費する開発者にとってどのようにしてより「フレンドリー」にすることができるかについての意見を探しています。
編集1
Disposing イベントの使用方法に関する質問があったので、コードをいくつか示します (重要な部分のみ抜粋)。
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);
}
解決
何かが足りないのかもしれませんが、なぜ API に新しいメソッドを追加するのでしょうか?オブジェクトがコンテナーに追加されるときに、キャストしてそれが IDisposable かどうかを確認し、そうである場合は適切に処理できます。
デストラクターが必要かどうかも疑問です。コンテナーが (Unity のような) IDisposable であると仮定すると、単に実装することができます。 基本的な廃棄パターン GC のオーバーヘッドを大幅に節約します。
該当する可能性のあるいくつかの質問: