我一直在努力学习服务层和存储库模式的工作原理。到目前为止,我已经编写了一个服务层和一个简单的存储库模式接口。但是,我经常看到文章声明存储库模式允许交换进出不同的数据存储,而不必更改消费代码。
在我的情况下,我希望能够支持读取和写入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();
}
然后提出两个问题:
我认为我绝对不了解如何正确实现存储库模式和服务层。我该如何设计存储库模式和服务层?
答案 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
)链接到具体类(ProductXmlRepository
或ProductXmlRepository
)。
答案 1 :(得分:0)
您的应用程序的解决方案应遵循依赖性倒置原则(http://deviq.com/dependency-inversion-principle/),以便至少有三个项目:
所有(或几乎所有)接口都应在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/)。