2013-12-15 55 views
0

我希望在我的MVC層中根本沒有存儲庫。如何在業務層中使用簡單注入器用於存儲庫

我在我的DAL項目圖層中有通用的EFRepository,IRepositoryPASContext(它從DbContext繼承)。

我已經在我的MVC項目下安裝了Simple Injector和快速入門,這讓我可以在每個控制器的構造函數中獲取我想要的存儲庫。

但在我的解決方案中,我也有BLL項目,我希望MVC層只與BLL層交談,因爲這是項目體系結構,未來我想在BLL層的類中添加邏輯。

而且我不想創建我的BLL層的上下文,但庫沒有構造函數這需要0參數,這是我的ProductBLL類:

public class BLLProducts 
{ 
    IRepository<Product> ProductRepository; 

    public BLLProducts(EFRepository<Product> Repository) 
    { 
     ProductRepository = Repository; 
    } 

    public ICollection<Product> getAll() 
    { 
     return ProductRepository.All().ToList(); 
    } 
} 

我怎麼能啓動的BLLProduct類從控制器或單元測試,而不創建一個存儲庫/上下文?所以我可以在這裏保留我的抽象。

我知道我需要以某種方式使用簡單的注射器在這裏,我只是不知道如何。

回答

1

從控制器的觀點來看,它只是一個注入BLLProducts進去,這樣的問題:

// constructor 
public HomeController(BLLProducts products) { 
    this.products = products; 
} 

從單元測試的角度來看,讓控制器取決於具體類是次優的(它違反了Dependency Inversion Principle)。這是次優的,因爲您現在需要創建一個BLLProducts實例並使用DbContext實例化該實例,但此DbContext特定於實體框架,該實體框架依賴於數據庫。這使得測試變得越來越難。你希望你的單元測試在沒有數據庫的情況下運行。

所以解決這個問題的方法是在抽象背後隱藏這個類。一個簡單的方法做,這是一個提取出接口這個類的:

public interface IBLLProducts { 
    ICollection<Product> getAll(); 
} 

這使得單元測試控制器容易得多。你必須做的唯一的事情就是讓這依靠這個新的接口:

public HomeController(IBLLProducts products) { 
    this.products = products; 
} 

您需要註冊在簡單的注射器這個IBLLProducts接口:

container.Register<IBBLProducts, BLLProducts>(); 

這整個模式還是有一些缺點它。例如,雖然Simple Injector可以爲你創建和配置一個DbContext,但你在哪裏調用SubmitChanges?當網絡請求結束時這樣做是一個非常糟糕的主意。我發現的唯一方便的解決方案是轉向更堅實的體系結構。例如,看看this question

+0

非常感謝!你會向我推薦什麼樣的SOLID架構,這與我目前的架構相近? ('BLL'通過存儲庫與'DAL'交談,'MVC'與使用簡單注入器的'BLL'交談) – jony89

+0

@ jony89:研究5個SOLID原則。它們爲您提供比不同架構風格(如3層架構)更重要的指導。計劃抽象,限制類的職責,並防止在添加功能時改變類。 – Steven

相關問題