C# 存储库模式-为什么我们需要接口?
我从互联网上读到,我得到了这一点,说接口是用来做这件事的C# 存储库模式-为什么我们需要接口?,c#,asp.net-mvc-3,repository-pattern,C#,Asp.net Mvc 3,Repository Pattern,我从互联网上读到,我得到了这一点,说接口是用来做这件事的 使用TDD方法 更换持久性引擎 但我无法理解界面在这一点上是如何发挥作用的替换持久性引擎。 让我们考虑一下,为 CaseRealPosiPosie < /P>创建一个基本的(没有泛型)存储库。 public class EmployeeRepository { public employee[] GetAll() { //here I'll return from dbContext or ObjectContex
- 使用TDD方法
- 更换持久性引擎
替换持久性引擎
。
让我们考虑一下,为<代码> CaseRealPosiPosie<代码> < /P>创建一个基本的(没有泛型)存储库。
public class EmployeeRepository
{
public employee[] GetAll()
{
//here I'll return from dbContext or ObjectContex class
}
}
那么界面是如何出现的呢
如果假设我创建了一个界面,为什么要使用向上转换呢?例如
IEmployee emp = new EmployeeRepository() ;
vs
EmployeeRepository emp = new EmployeeRepository();
请向我详细解释界面在存储库模式方面的其他有用之处。您将把存储库公开为一个界面:
public interface IEmployeeRepository
{
List<Employee> GetAll();
}
IEmployeeRepository myRepo = MyRepositoryFactory.Get<IEmployeeRepository>();
公共接口IEmployeeRepository
{
List GetAll();
}
这将允许您拥有许多不同的接口实现,例如默认实现:
public class EmployeeRepository : IEmployeeRepository
{
public List<Employee> GetAll()
{
// Return from db.
}
}
公共类EmployeeRepository:IEEmployeeRepository
{
公共列表GetAll()
{
//从数据库返回。
}
}
或者一个测试:
public class TestEmployeeRepository : IEmployeeRepository
{
public List<Employee> GetAll()
{
// Stub some dummy data.
}
}
公共类TestEmployeeRepository:IEEmployeeRepository
{
公共列表GetAll()
{
//存根一些虚拟数据。
}
}
使用存储库的代码只对使用接口感兴趣:
public interface IEmployeeRepository
{
List<Employee> GetAll();
}
IEmployeeRepository myRepo = MyRepositoryFactory.Get<IEmployeeRepository>();
IEmployeeRepository myRepo=MyRepositoryFactory.Get();
秘密酱汁是工厂,或者是将接口解析为可用类型的另一种机制(依赖项注入框架,如Ninject或Castle Windsor将履行此角色)
关键是,消费代码不关心实现,只关心契约(接口)。这使您可以非常轻松地交换用于测试目的的实现,并促进松耦合
只是澄清一下,接口的使用和存储库模式之间没有联系,具体来说,这只是另一种可以利用它们的模式
那么界面是如何出现的呢
像这样:
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执行此操作的示例:
~/App_Start/NinjectWebCommon.cs
代码中,您只需决定将EF实现与一行代码一起使用:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IEmployeeRepository>().To<EmployeeRepositoryEF>();
}
私有静态无效注册服务(IKernel内核)
{
kernel.Bind().To();
}
我还邀请您在ASP.NET MVC中查看关于TDD和DI的信息。感谢您的快速回复。。。还有一个问题,为什么升级
ieemployeeemp=newemployeerepository()代码>vs雇员安置emp=新雇员安置()代码>?精彩的答案,每一个解释都是值得的。现在我明白了事情是如何运作的。谢谢,我不能将这个答案标记为已接受,因为我的分数低于15分,一旦我得到答案,我将接受这个答案。谢谢那篇文章。。假设我在依赖注入框架中配置了EmployeeRepositoryEF
,我的控制器将使用这个EmployeeRepositoryEF
,但是如果我想在同一个控制器中使用2个实现呢。。如果这个问题很愚蠢,我很抱歉..在示例I提供程序中,控制器在其构造函数中需要一个IEmployeeRepository
实例。只能通过一个实现。另一方面,您可能有另一个控制器,它可能需要不同的接口实现。这是完全可能的。您只需要配置DI框架,以便它在ControllerA中注入实现A,在ControllerB中注入实现B。当然,不同的DI框架的语法会有所不同。谢谢你,现在它对我来说很有意义,而且非常清晰。我完全同意这个概念,但假设我的项目中有1000个存储库。我认为如果我创建1000个接口,代码会有味道。应该是保持DI的一种方式,但避免有这么多接口。