存储库模式-为什么我们确实需要接口? [英] Repository pattern - Why exactly do we need Interfaces?

查看:62
本文介绍了存储库模式-为什么我们确实需要接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从互联网上读到了这一点,它说接口用于此

I have read from internet I got this points which says Interfaces is used for this

  • 使用TDD方法
  • 替换持久性引擎

但是我无法理解接口Replace persistance engine在这一点上将如何有用. 让我们考虑一下我正在为EmployeeRepository

But I'm not able to understand how interface will be usefull to this point Replace persistance engine. lets consider I'm creating a basic(without generics) repository for EmployeeRepository

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

那么界面如何呈现出来?

So how interfaces come into picture?

,如果假设我创建了一个接口,为什么要使用上播?例如

and if suppose i created an interface why upcasting is used ? for e.g

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

请准确地向我解释一下接口以及在存储库模式方面的其他用途.

Please explain me precisely and also other usefullness of Interface in regard to Repository Pattern.

推荐答案

那么界面如何呈现出来?

So how interfaces come into picture ?

赞:

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

然后您可以根据需要实现多种实现方式:

and then you could have as many implementations as you like:

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方法.

As you can see it's not really important how we implement the repository. What's important is that all repositories and implementations respect the defined contract (interface) and all posses a GetAll method returning a list of employees.

然后您将拥有一个使用此接口的控制器.

And then you will have a controller which uses this interface.

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

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

看看控制器如何不再依赖于存储库的特定实现?它所需要知道的就是该实现遵守合同.现在,您需要做的就是配置您最喜欢的依赖项注入框架,以使用所需的实现.

See how the controller no longer depends on a specific implementation of the repository? All it needs to know is that this implementation respects the contract. Now all that you need to do is to configure your favorite dependency injection framework to use the implementation you wish.

下面是使用Ninject进行此操作的示例:

Here's an example of how this is done with Ninject:

  1. 安装 Ninject.MVC3 NuGet
  2. 在生成的~/App_Start/NinjectWebCommon.cs代码中,您只需决定将EF实现与一行代码一起使用:

  1. Install the Ninject.MVC3 NuGet
  2. In the generated ~/App_Start/NinjectWebCommon.cs code you simply decide to use the EF implementation with a single line of code:

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

通过这种方式,您不再需要对这些存储库类进行任何手动实例化,而不必担心上载或其他问题.依赖项注入框架将为您管理它们,并将负责将已定义的实现注入到控制器构造函数中.

This way you no longer need to do any manual instantiations of those repository classes and worry about upcasting or whatever. It is the dependency injection framework that manages them for you and will take care of injecting the defined implementation into the controller constructor.

只需修改此配置,您就可以切换数据访问技术,而无需触碰控制器中的任何一行代码.这样,隔离中的单元测试也可以发挥作用.由于您的控制器代码现在已弱耦合到存储库(由于我们引入了接口),因此在单元测试中,您需要做的就是在存储库上提供一些模拟实现,以允许您定义其行为.这使您可以对索引控制器操作进行单元测试,而无需依赖数据库或任何其他依赖项.完全隔离.

And by simply modifying this configuration you could switch your data access technology without touching a single line of code in your controller. That's way unit testing in isolation also comes into play. Since your controller code is now weakly coupled to the repository (thanks to the interface we introduced) all you need to do in the unit test is to provide some mock implementation on the repository which allows you to define its behavior. This gives you the possibility to unit test the Index controller action without any dependency on a database or whatever. Complete isolation.

我还邀请您查看有关ASP.NET MVC中TDD和DI的后续文章.

I also invite you to checkout the following articles about TDD and DI in ASP.NET MVC.

这篇关于存储库模式-为什么我们确实需要接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆