使用存储库模式提供对不同数据存储的访问

本文关键字:存储 数据 访问 模式 | 更新日期: 2023-09-27 18:20:54

我一直在努力学习服务层和存储库模式是如何工作的。到目前为止,我已经编写了一个服务层和一个简单的存储库模式接口。然而,我经常看到一些文章指出,存储库模式允许在不必更改消耗代码的情况下交换不同的数据存储。

在我的情况下,我希望能够支持将应用程序数据读取和写入CSV和/或XML文件。这是我不理解如何使用存储库模式正确实现这一点的部分。每个数据存储是否应该有一个存储库?

ProductCsvRepository : IProductRepository
ProductXmlRepository : IProductRepository

然而,如果我这样做,那么服务层就必须意识到底层的数据存储,这打破了能够轻松地交换不同数据存储的想法。

那么我是否需要一个像这样的服务层?

private readonly IProductXmlRepository _productXmlRepository;
private readonly IProductCsvRepository _productCsvRepository;
public ProductService()
{
    _productXmlRepository = new IProductXmlRepository();
    _productCsvRepository = new IProductCsvRepository();
}
public ICollection<Product> GetAllXml()
{
    return _productXmlRepository.GetAllCsv();
}
public ICollection<Product> GetAll()
{
    return _productCsvRepository.GetAllXml();
}

这就提出了两个问题:

  • 这肯定打破了消费代码需要知道数据存储是什么的想法吗
  • 如果消费代码确实需要了解数据存储,例如"文件>导出为"类型的功能,该怎么办?导出功能实际上应该是使用适当CSV或XML服务的不同服务吗

我认为我显然不理解如何正确地实现存储库模式和服务层。我应该如何设计存储库模式和服务层?

使用存储库模式提供对不同数据存储的访问

看看依赖注入和插件模式。它们支持注入存储库的具体实现。然后,您的服务层只有一个对IProductRepository的引用,并且会注入一个具体的存储库。大致如下:

public class ProductService
{
    private readonly IProductRepository _productRepository;
    public ProductService(IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }
}

public class ConsumingClass {
{
    private readonly IProductService _productService = new ProductService(new ProductXmlRepository());
    // methods to use the the product service
}

但更好的方法是使用反转控制容器,如NInjector或SimpleInjector。这些框架可以用于基于xml配置将抽象类(IProductRepository)链接到具体类(ProductXmlRepositoryProductXmlRepository)。

应用程序的解决方案应该按照依赖反转原则进行结构化(http://deviq.com/dependency-inversion-principle/),因此至少有三个项目:

  • 核心
  • 基础设施
  • 您的UI项目

所有(或几乎所有)接口都应该在Core中声明(例如IProductRepository)。您的接口实现属于引用Core的Infrastructure。最后,您的UI项目应该引用Core,但不一定引用Infrastructure(学习如何在不引用项目的情况下使用项目中的类型:http://blog.falafel.com/use-types-from-project-without-referencing/)。

有了这个体系结构,就可以使用依赖项注入(http://deviq.com/dependency-injection/)在运行时注入给定类型的所需实现,这提供了极大的灵活性和可测试性。

设置具有项目之间适当依赖关系的解决方案对于成功使用此方法至关重要,因为传统的UI->BusinessLayer->DataLayer设置不允许反转依赖关系。一旦以这种方式设置了解决方案,就应该遵循显式依赖性原则(http://deviq.com/explicit-dependencies-principle/)在您的所有UI和服务代码中。