Mes*_*son 39 c# repository-pattern asp.net-mvc-3
我从互联网上读到了我得到了这一点,其中说接口用于此
但是我无法理解接口在这一点上的用途Replace persistance engine
.让我们考虑我正在创建一个基本的(没有泛型)存储库EmployeeRepository
public class EmployeeRepository
{
public employee[] GetAll()
{
//here I'll return from dbContext or ObjectContex class
}
}
Run Code Online (Sandbox Code Playgroud)
界面界面如何形成?
如果假设我创建了一个接口,为什么要使用向上转换?例如
IEmployee emp = new EmployeeRepository() ;
vs
EmployeeRepository emp = new EmployeeRepository();
Run Code Online (Sandbox Code Playgroud)
请详细解释我,以及关于存储库模式的接口的其他有用性.
Dar*_*rov 78
界面界面如何形成?
像这样:
public interface IEmployeeRepository
{
Employee[] GetAll();
}
Run Code Online (Sandbox Code Playgroud)
然后你可以拥有任意数量的实现:
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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我们如何实现存储库并不重要.重要的是,所有存储库和实现都遵循已定义的合同(接口),并且所有存储库都拥有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);
}
}
Run Code Online (Sandbox Code Playgroud)
了解控制器如何不再依赖于存储库的特定实现?它需要知道的是,这种实现尊重合同.现在,您需要做的就是配置您喜欢的依赖注入框架以使用您希望的实现.
以下是使用Ninject完成此操作的示例:
在生成的~/App_Start/NinjectWebCommon.cs
代码中,您只需使用一行代码来决定使用EF实现:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IEmployeeRepository>().To<EmployeeRepositoryEF>();
}
Run Code Online (Sandbox Code Playgroud)这样,您不再需要对这些存储库类进行任何手动实例化,并担心向上转换或其他任何问题.它是依赖注入框架,它为您管理它们,并将负责将定义的实现注入到控制器构造函数中.
通过简单地修改此配置,您可以切换数据访问技术,而无需触及控制器中的单行代码.这种方式单独进行单元测试也会发挥作用.由于您的控制器代码现在与存储库弱耦合(感谢我们引入的接口),您在单元测试中需要做的就是在存储库上提供一些模拟实现,允许您定义其行为.这使您可以对Index控制器操作进行单元测试,而不依赖于数据库或其他任何操作.完全隔离.
我还邀请您查看ASP.NET MVC中有关TDD和DI 的以下文章.
Ada*_*rth 14
您将把您的存储库公开为一个接口:
public interface IEmployeeRepository
{
List<Employee> GetAll();
}
Run Code Online (Sandbox Code Playgroud)
这将允许您有许多不同的接口实现,例如默认的:
public class EmployeeRepository : IEmployeeRepository
{
public List<Employee> GetAll()
{
// Return from db.
}
}
Run Code Online (Sandbox Code Playgroud)
或测试一:
public class TestEmployeeRepository : IEmployeeRepository
{
public List<Employee> GetAll()
{
// Stub some dummy data.
}
}
Run Code Online (Sandbox Code Playgroud)
您使用存储库的代码只对使用该接口感兴趣:
IEmployeeRepository myRepo = MyRepositoryFactory.Get<IEmployeeRepository>();
Run Code Online (Sandbox Code Playgroud)
秘诀是工厂,或者将接口解析为可用类型的其他机制(诸如Ninject之类的依赖注入框架,或者Castle Windsor将履行此角色).
关键是,消费代码不关心实现,只关注合同(接口).这使您可以非常轻松地更换实现以进行测试,并促进松散耦合.
只是为了澄清,接口的使用和存储库模式之间没有任何关联,它只是可以利用它们的另一种模式.