2017-08-28 34 views
1

在我的應用我有很多的服務,我用的是以下模式: 在同一文件中,我定義它是由IoC容器如下控制的靜態工廠方法的接口:IoC的實例化最新時間可能

public interface ISomethingService { 
    Task DoSomethingAsync(int id); 
} 

public class SomethingServicFactory : ServiceFactory<ISomethingService > { } 

public class ServiceFactory<T> 
{ 
    public static Func<T> CreateClosure; 
    public T GetDefault() => CreateClosure(); 
} 

創建和配置IoC容器後:

SomethingServicFactory .CreateClosure =() => 
    Container.GetInstance<ISomethingService >(); 

在我的應用。稍後,當我需要一個SomethingService:

var somethingService= new SomethingService().GetDefault(); 

這使我可以推遲創建,直到最後一刻仍然控制使用容器的服務創建。我剛開始使用SimpleInjector。 更重要的是,它允許我創建服務實例,並輕鬆傳遞參數,同時控制IoC。

這個模式幫助我的一個很好的例子是需要填充數據的WPF XAML實例化用戶控件(即從數據庫查找值)。在後面的代碼中,我能夠輕鬆創建一個DbContext並從數據庫中獲取數據。但是,我也在整個應用程序中使用它。

我擔心我錯過了使用此模式的重大設計/體系結構問題,我正在尋找IoC專家對此模式的評論。

+0

這聽起來很像'懶惰' – Nkosi

回答

6

您的設計公開以下代碼味道和反模式:

  • Temporal Coupling:您CreateClosure屬性,迫使你在創建後初始化服務工廠。當你忘記這一點時,應用程序將在運行時失敗。時間耦合是一種代碼味道。
  • Ambient ContextCreateClosure充當環境上下文(非常類似於Singleton設計模式,但可以使用靜態方法或屬性更改值)。這會導致類的依賴隱藏,而不是使用類的構造函數進行「靜態聲明」。在Dependency Injection in .NET 2nd edition中,我們將Ambient Context視爲一種反模式(請參閱第5章)。
  • Dependency Inversion Principle違規:您的工廠是具體類,而DIP促進與界面交談。因此,您的代碼變得強烈耦合,難以測試。
  • Abstract Factories are a code smell:應用依賴注入時,工廠的實用性會消失。特別是在您的應用程序中爲每個抽象提供一個工廠的想法絕對是不行的。

相反,與依賴注入,一切都變得容易多了:當我們將構造器注入,我們可以簡單地注入ISomethingService到它的消費者。這:

  • 清楚哪些依賴一個類,通過觀察構造
  • 允許DI容器組成適合你的對象圖,並做分析和診斷圖表上的
  • 允許容器管理對象的生命週期
  • 刪除需要有工廠(因爲容器將扮演這個角色)
  • 減少類的依賴關係的數量。不需要2個(一個用於工廠,一個用於服務),你只需要一個(用於服務)。
+0

首先,感謝您花時間寫出明確的答案。 – user1221237