存储库模式 - 为什么我们需要接口
本文关键字:接口 我们 为什么 模式 存储 | 更新日期: 2023-09-27 18:34:23
我从互联网上读到了这一点,它说接口用于此
- 使用 TDD 方法
- 替换持久性引擎
但是我无法理解界面将如何用到这一点Replace persistance engine
.让我们考虑一下我正在为EmployeeRepository
创建一个基本的(没有泛型(存储库
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
{
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 完成此操作的示例:
- 安装 Ninject.MVC3 NuGet
在生成的
~/App_Start/NinjectWebCommon.cs
代码中,只需决定将 EF 实现与一行代码一起使用:private static void RegisterServices(IKernel kernel) { kernel.Bind<IEmployeeRepository>().To<EmployeeRepositoryEF>(); }
这样,您不再需要对这些存储库类进行任何手动实例化,也不必担心向上转换或其他什么。它是为您管理它们的依赖注入框架,并将负责将定义的实现注入控制器构造函数。
通过简单地修改此配置,您可以切换数据访问技术,而无需接触控制器中的任何一行代码。这就是孤立的单元测试也发挥作用的方式。由于您的控制器代码现在与存储库弱耦合(由于我们引入的接口(,因此您在单元测试中需要做的就是在存储库上提供一些模拟实现,以允许您定义其行为。这使您可以对索引控制器操作进行单元测试,而无需依赖数据库或其他任何内容。完全隔离。
我还邀请您查看以下有关 MVC 中的 TDD 和 DI ASP.NET 文章。
您可以将存储库公开为接口:
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或Castle Windsor将履行此角色(。
关键是,消费代码不关心实现,只关心合约(接口(。这使您可以非常轻松地交换用于测试目的的实现,并促进松散耦合。
澄清一下,接口的使用与存储库模式之间没有联系,它只是另一种可以使用它们的模式。