Repository模式 - 到底为什么我们需要的接口?(Repository pattern -

2019-07-29 10:35发布

我从网上看我这点,这表示接口用于此

  • 使用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();

请准确,也给我解释一下界面的其他有用性对于Repository模式。

Answer 1:

因此,如何界面进入图片?

像这样:

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>(); } 

这样,您不再需要做那些库类的任何手动实例和担心上溯造型或什么的。 它是依赖注入框架来管理他们为你,并会采取注入实现定义到控制器构造函数的照顾。

而且通过简单地修改这个配置,你可以切换你的数据访问技术而不碰一行代码在你的控制器。 这是一个在隔离的方式进行单元测试也开始发挥作用。 由于控制器代码现在弱耦合到存储库(感谢我们介绍了接口),所有你需要在单元测试中做的是提供允许您定义其行为的一些库模拟实现。 这给你的可能性,单元测试没有数据库或任何任何依赖性索引控制器动作。 完全隔离。

我还请你签出以下文章了解TDD和DI在ASP.NET MVC。



Answer 2:

你会暴露你的仓库作为一个接口:

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,或温莎城堡将发挥这一作用)。

问题是, 消费代码不关心执行 ,只有合同 (接口)。 这使您可以很轻松地换出用于测试目的的实现和促进松耦合。

只是为了澄清,还有就是使用的界面和专门的存储库模式之间没有任何联系,它只是另一种模式,可以使它们的使用。



文章来源: Repository pattern - Why exactly do we need Interfaces?