使用存储库模式

时间:2015-11-07 11:02:58

标签: c# .net oop design-patterns software-design

我一直在努力学习服务层和存储库模式的工作原理。到目前为止,我已经编写了一个服务层和一个简单的存储库模式接口。但是,我经常看到文章声明存储库模式允许交换进出不同的数据存储,而不必更改消费代码。

在我的情况下,我希望能够支持读取和写入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();
}

然后提出两个问题:

  • 这肯定打破了消费代码需要知道数据存储是什么的想法?
  • 在消费代码 需要了解数据存储的情况下,例如“文件&gt;导出为”类型功能?导出功能实际上应该是使用适当的CSV或XML服务的不同服务吗?

我认为我绝对不了解如何正确实现存储库模式和服务层。我该如何设计存储库模式和服务层?

2 个答案:

答案 0 :(得分:2)

看看依赖注入和插件模式。它们支持注入存储库的具体实现。然后,您的服务层只有一个对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
}

但更好的方法是使用像NInject或SimpleInjector这样的控件容器的反转。这些框架可用于根据xml配置将抽象类(IProductRepository)链接到具体类(ProductXmlRepositoryProductXmlRepository)。

答案 1 :(得分:0)

您的应用程序的解决方案应遵循依赖性倒置原则(http://deviq.com/dependency-inversion-principle/),以便至少有三个项目:

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

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

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

使用此方法成功解决项目之间正确的依赖关系至关重要,因为传统的用户界面 - &gt;业务层 - &gt;数据层设置不允许您反转依赖项。一旦以这种方式设置了解决方案,就应该在所有UI和服务代码中遵循显式依赖关系原则(http://deviq.com/explicit-dependencies-principle/)。