2011-02-07 54 views
1

我偶然發現了一些代碼,我很好奇爲什麼它會這樣。構造具有函數作爲依賴注入手段的對象

有兩個構造函數,主要是在代碼中調用,第二個是在依賴注入測試中使用。第二個構造函數接受一個返回對象的函數,而不是對象本身的一個實例。

MainConstructor() 
:this(() => Factory.Current.GetInstance<IQueryService>()){ 
} 

SecondConstructor(Func<IQueryService> getQueryService){ 
} 

我很好奇你會從傳遞函數而不是實例中獲得好處。

+1

什麼是一種奇怪的方式來做依賴注入。 – Snowbear 2011-02-07 19:11:13

回答

1

有做這樣的事情幾種可能的好處:

  1. 脫鉤:通過允許呼叫者委託傳遞,而不是一個實例,無論是主叫用戶和被叫(在你的案例正在構建的類)可以從傳遞的對象和它來自的地方分離。
  2. 懶惰收購:通過傳遞委託,可以以懶惰的方式獲取實例。換句話說,構造函數原則上可以緩存委託並在最後可能的時刻調用它,只有當實際需要實例時纔會調用它。如果實例從不需要,它可能永遠不會被創建。
  3. 可重複性:通過傳遞委託而不是實例,該類可以緩存用於按需創建查詢服務的機制。通過這種方式,代表充當工廠,允許按需創建所需類型的實例。
0

使用Func<T>允許延後創建產品,它是可選的依賴關係非常有用 - 例如在類中的方法之一可能是這樣的:

public void SomeMethod() 
{ 
    if(someCondition) 
    { 
     IQueryService service = this.getQueryService(); 
     service.Execute(): 
    } 
} 

如果IQueryService是昂貴的創建這可以提高工作效率如果someCondition從未評估爲真。

0

Func<IQueryService>在這種情況下真的是變相的抽象工廠。所以問題的確是:「你爲什麼要使用工廠而不是注入對象本身?」

您在使用工廠時,此類實例的生命週期對消費者而言很重要,您需要控制該實例的生命週期,或者該實例的創建成本很高。很好的例子是當對象實現IDisposable。一次性物品通常需要明確控制。

我個人不喜歡使用Func<T>代表作爲工廠,因爲它使您的代碼更加清晰。而不是根據Func<IQueryService>,讓班級依賴於IQueryServiceFactory。這使得你的代碼更加明確。這種方法的缺點當然是你將不得不編寫更多的代碼(不多,但仍然)。

第二個構造函數使用依賴注入模式。然而,第一個構造函數是Poor Man's DI的示例。這是一種允許爲單元測試注入依賴關係的方式,但是可以節省您爲生產代碼使用依賴注入框架的需求。這種方法的缺點是需要依賴容器(在您的案例中爲Factory),這種模式稱爲Service Locator。另一個缺點是它使一個類所需的依賴性不太明顯。

相關問題