由於您希望在多線程應用程序中使用此構造,並希望跨線程重複使用同一實例(如您在註釋中所暗示的那樣),因此您將無法通過配置DI容器來解決此問題。
由於競爭條件,您無法在丟棄後配置要更新的對象。想象一下下面的場景:
- 線程1從容器中請求一個實例。
- 這是第一個請求,容器將創建一個新實例。
- 線程2從容器
- 請求的實例的容器返回步驟創建的實例2.
- 線程1與實例來完成,並調用
Dispose
。
- 線程2開始使用該實例,但實例已處理,並引發異常。
問題是應用程序將獲得對可以處置的實例的引用。
儘量避免通過重新設計您的應用程序來做到這一點,如果可以的話。公開實現IDisposable
的服務類型是一種不好的做法,因爲IDisposable
是泄漏抽象。我個人的偏好甚至是阻止這些服務的任何實現來實現IDisposable
。在大多數情況下,重新設計可以防止您必須這樣做。
如果您需要使用IDisposable
對象,通常的方法是創建並注入創建這些對象的工廠。這樣消費者就可以安全地處理這樣一個對象,沒有任何問題。
這裏的一般問題是很難創建實際上是線程安全的實現IDisposable
的對象。
如果你真的想要這個,你可以嘗試創建一個引用計數的裝飾器。在下面的修飾器中查找實例。它包裝IService
並實施IService
。 IService
執行IDisposable
。裝飾器需要一個允許創建實例的委託。對象的創建和處理受lock
聲明的保護,並且裝飾器計算調用者對它的引用。在最後一位消費者處理裝飾器後,它將處理該對象並創建一個新對象。
public class ScopedServiceDecorator : IService
{
private readonly object locker = new object();
private Func<IService> factory;
private IService currentInstance;
private int referenceCount;
public ScopedServiceDecorator(Func<IService> factory)
{
this.factory = factory;
}
public void SomeOperation()
{
IService instance;
lock (this.locker)
{
instance = this.GetInstance();
this.referenceCount++;
}
instance.SomeOperation();
}
public void Dispose()
{
IService instance = null;
lock (this.locker)
{
this.referenceCount--;
if (this.referenceCount == 0)
{
instance = this.wrappedService;
this.wrappedService = null;
}
}
// Dispose the object outside the lock for performance.
if (instance != null)
{
instance.Dispose();
}
}
private IService GetInstance()
{
if (this.wrappedService == null)
{
this.wrappedService = this.factory();
}
return this.wrappedService;
}
}
請注意,這個實現仍然是有缺陷的,因爲以下原因,:
- 調用
Dispose
多次打破了裝飾。
- 當消費者多次撥打
SomeOperation
(或IService
有多個方法)時,實施將中斷。
很難創建一個按預期運行的裝飾器。這樣做的一個簡單方法是通過序列化訪問對象,但是當你這樣做時,你可能想要爲每個線程使用單個實例。這會容易得多。
我希望這會有所幫助。
你正在運行什麼類型的應用程序?它是一個多線程應用程序嗎? – Steven 2011-04-26 06:34:11
是的。像每個線程實例這樣的東西在這裏沒有用處。 – anthony 2011-04-26 06:43:05