1

我們已經創建了一個單獨的對象(SsoSettingsProvider)中,我們與生活方式注入對象PerWebRequest(IReservationService在我們的例子是WCF客戶端),溫莎城堡PerWebRequest對象。在構造函數中,我們使用這個對象來獲取一些數據,並將這些數據放在一個專用字段中。在Singleton對象沒有注入引用它在現場

public class SsoSettingsProvider : ISsoSettingsProvider 
    { 
     readonly LogonSettings _logonSettings; 


     public SsoSettingsProvider(IReservationService reservationService) 
     { 
      _logonSettings = reservationService.GetSSOSettings(); 
     }   
    } 

如果我們看一下可能的生活方式不匹配在溫莎城堡,它說:

「組件‘SsoSettingsProvider/ISsoSettingsProvider’生活方式 辛格爾頓與生活方式 取決於‘後期綁定IReservationService’PerWebRequest這種通常不需要依賴項,並且可能會導致各種類型的錯誤。「

這個信息說有唯一的可能性,但在這種情況下,我認爲這不是一個問題,因爲注入的對象並不在現場引用,因此它可以被垃圾收集。我對嗎 ?

+0

請閱讀[本文](http://blog.ploeh.dk/2014/06/02/captive-dependency/)以瞭解問題。 – Steven

+0

感謝您的文章。我意識到這種行爲,但情況並非如此。將文章映射到我的情況,我們應該在'SsoSettingsProvider'的字段中引用'IReservationService'。在我的例子中它使用了一次。 – RedgoodBreaker

+1

而[本文](http://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/)也適用於您的情況。 – Steven

回答

1

在這種情況下,我認爲這不是一個問題,因爲注入的對象沒有在字段中引用,因此它可以被垃圾回收。我對嗎?

溫莎城堡警告約Captive Dependencies。主要問題不是垃圾收集,而是一個類將重用一個不打算重用的實例。

簡單的例子是當您將DbContext注入配置爲單例的類中時。雖然這會導致DbContext在其單身消費者超出範圍(通常是應用程序結束時)之前保持活動狀態。但是,DbContext不應該在多個請求中重複使用。首先,因爲它不是線程安全的。最重要的是,它很快就會過時,導致它返回緩存的數據,而不是重新查詢數據庫。

爲此,我們register DbContext typically as Scoped。然而,這意味着所有的消費者最多隻要生活在DbContext之下,就可以防止它破壞應用程序。這正是Castle所警告的。

但在您的情況下,您不會將IReservationService存儲到SsoSettingsProvider的私人字段中。這仍然是一個問題,因爲期望IReservationService返回的對象不會超過IReservationService(否則IReservationService將被註冊爲單例)是合理的。由於從SsoSettingsProvider的角度來看,無法知道是否安全地存儲LogonSettings,所以好於

最重要的是,如表達式here所示,注入構造函數根本不應該使用它們的依賴關係。這導致緩慢和不可靠的物體組成。

所以,即使你可能已經分析了您的設計和肯定知道這個作品你的具體情況,我建議你做以下事情之一:

  • 商店IReservationService私人領域SsoSettingsProvider和僅當SsoSettingsProvider的成員之一被呼叫並且阻止存儲LogonSettings時,請致電GetSSOSettings。這會迫使你作出SsoSettingsProvider範圍或IReservationService單身。 IReservationService是否可以是單身只有你可以找到的東西。
  • 如果SsoSettingsProvider僅在LogonSettings感興趣,LogonSettings是應用程序啓動後,不會改變一個恆定值,你應該直接在SsoSettingsProvider的構造注入LogonSettings。這簡化了SsoSettingsProvider並將LogonSettings加載到組合根。
+0

在我的情況下,我有不變的價值。所以我認爲最好的選擇是通過'.UsingFactoryMethod()' – RedgoodBreaker

+0

如果它是一個在應用程序啓動後沒有改變的值,使用'.Instance'將它註冊爲單例實例。這比使用'.UsingFactoryMethod'要容易得多。 – Steven

+0

但我必須調用'SsoSettingsProvider' WCF客戶端從遠程服務獲取'LogonSettings'。所以我必須創建實例'SsoSettingsProvider' – RedgoodBreaker

相關問題