2012-05-16 110 views
33

我從網上看我這點,這表示接口用於此存儲庫模式 - 爲什麼我們需要接口?

  • 使用TDD方法
  • 更換持久性引擎

但我無法理解如何界面有用到這個點Replace persistance engine。 讓我們考慮我創造EmployeeRepository

public class EmployeeRepository 
{ 
    public employee[] GetAll() 
    { 
    //here I'll return from dbContext or ObjectContex class 
    } 
} 

一個基本的(不使用泛型)資源庫,如何界面進入圖片?

如果我想創建一個接口,爲什麼使用upcasting?例如

IEmployee emp = new EmployeeRepository() ; 
vs 
EmployeeRepository emp = new EmployeeRepository(); 

請詳細解釋我,以及接口在存儲庫模式方面的其他有用性。

回答

69

那麼接口如何進入畫面?

像這樣:

public interface IEmployeeRepository 
{ 
    Employee[] GetAll(); 
} 

,然後只要你喜歡,你可以有儘可能多的實現:

public class EmployeeRepositoryEF: IEmployeeRepository 
{ 
    public Employee[] GetAll() 
    { 
     //here you will return employees after querying your EF DbContext 
    } 
} 

public class EmployeeRepositoryXML: IEmployeeRepository 
{ 
    public Employee[] GetAll() 
    { 
     //here you will return employees after querying an XML file 
    } 
} 

public class EmployeeRepositoryWCF: IEmployeeRepository 
{ 
    public Employee[] GetAll() 
    { 
     //here you will return employees after querying some remote WCF service 
    } 
} 

and so on ... you could have as many implementation as you like 

正如你可以看到我們是如何實現資源庫,就不是很重要。重要的是,所有的存儲庫和實現都遵守所定義的合同(接口),並且都有一個返回員工列表的方法GetAll

然後你將有一個使用這個接口的控制器。

public class EmployeesController: Controller 
{ 
    private readonly IEmployeeRepository _repository; 
    public EmployeesController(IEmployeeRepository repository) 
    { 
     _repository = repository; 
    } 

    public ActionResult Index() 
    { 
     var employees = _repository.GetAll(); 
     return View(employees); 
    } 
} 

看看控制器不再依賴於存儲庫的特定實現嗎?所有它需要知道的是,這個實現尊重合同。現在,您需要做的就是配置您最喜歡的依賴注入框架,以使用您希望的實現。

下面是如何與Ninject做了一個例子:

  1. 安裝Ninject.MVC3的NuGet
  2. 在生成~/App_Start/NinjectWebCommon.cs代碼,你只需決定使用EF實現用一個單一的代碼行:

    private static void RegisterServices(IKernel kernel) 
    { 
        kernel.Bind<IEmployeeRepository>().To<EmployeeRepositoryEF>(); 
    }   
    

這樣,您不再需要做任何手工實例這些存儲庫類和擔心upcasting或任何。它是爲您管理它們的依賴注入框架,並負責將定義的實現注入到控制器構造函數中。

通過簡單修改此配置,您可以切換數據訪問技術,而無需觸摸控制器中的單行代碼。這樣單元測試的方式也在發揮作用。由於您的控制器代碼現在與存儲庫弱耦合(得益於我們介紹的接口),您需要在單元測試中做的所有事情是在存儲庫上提供一些模擬實現,以便您定義其行爲。這使您可以單元測試索引控制器動作而不依賴於數據庫或其他任何東西。完全隔離。

我還邀請您在ASP.NET MVC中檢查關於TDD和DI的following articles

+1

奇妙的答案,每個解釋都值得..現在我知道它是如何工作的..謝謝你,我不能將這個答案標記爲接受,因爲我的分數低於15,只要我賺取我會接受這個答案。 – Meson

+0

感謝那篇文章..並假設如果我配置'EmployeeRepositoryEF'在我的依賴注入框架中,我的控制器將消耗此'EmployeeRepositoryEF',但是如果我想要在同一控制器中使用2實現..如果這個問題愚蠢im非常抱歉.. – Meson

+2

在示例I提供程序中,控制器在其構造函數中需要一個'IEmployeeRepository'實例。只有一個實現可以通過。另一方面,你可能有另一個控制器可能需要不同的接口實現。這完全有可能。您只需配置您的DI框架,以便將ControllerA和ControllerB中的ImplementationB注入到ControllerA中。不同的DI框架之間的語法當然會有所不同。 –

14

你會暴露你的資料庫作爲一個接口:

public interface IEmployeeRepository 
{ 
    List<Employee> GetAll(); 
} 

這將讓你有許多不同的實現接口的如默認一個:

public class EmployeeRepository : IEmployeeRepository 
{ 
    public List<Employee> GetAll() 
    { 
     // Return from db. 
    } 
} 

還是一個測試一:

public class TestEmployeeRepository : IEmployeeRepository 
{ 
    public List<Employee> GetAll() 
    { 
     // Stub some dummy data. 
    } 
} 

您的代碼消耗存儲庫是接着僅在使用界面感興趣:

IEmployeeRepository myRepo = MyRepositoryFactory.Get<IEmployeeRepository>(); 

祕密醬是出廠,或另一種機制,通過它來解決界面成可用類型(依賴注入框架如Ninject,或城堡溫莎將履行這一職責)。

的一點是,消費代碼不關心執行,只有合同(接口)。這使您可以非常容易地爲了測試目的而更換實現,並促進鬆散耦合。

只是爲了澄清一下,接口的使用和存儲庫模式之間沒有任何聯繫,它只是另一種可以利用它們的模式。

+0

感謝您的快速響應......還有一個問題爲什麼向上轉換爲什麼向上轉換'IEmployee emp = new EmployeeRepository();'vs'EmployeeRepository emp = new EmployeeRepository();'? – Meson

相關問題