Skip to main content
 首页 » 编程设计

c#之我应该在哪里存储对象集合以方便 DI/测试

2024年02月20日30kevingrace

我试图弄清楚从数据库中检索到的应用程序运行所必需的对象集合的存储位置。例如,我正在尝试重新设计一个使用 Report 的报告应用程序和 Parameter对象。这些对象以 XML 格式存储在数据库中。在最简单的层面上,定义的集合可以存储为 Dictionary<string, string>。 (对象键、对象定义 XML)。

我想实现一个工厂模式来处理从它们的 XML 定义创建这些对象。

IReport GetReport(string reportName) 
IParameter GetParameter(string parameterName) 

这些方法要求工厂存储报告和参数的集合。

所以,我的问题是:

  1. 工厂应该完全存储对象集合还是只负责根据定义创建对象,将方法更改为 IReport GetReport(string reportDefinition)
  2. 如果工厂要存储对象,我是否应该简单地将集合注入(inject)到工厂类的构造函数中?
  3. 单元测试 - 如果我走 #2 的路线,我想我会直接将我的测试集合注入(inject)工厂,对吗?

请您参考如下方法:

您可以通过多种方式构建它,这些方式都遵循 SRP (Single Responsibility Principle) .

一种方法如下:有一个接口(interface),IReportLoadingService,带有一个接收报告标识符并返回IReport实例的方法。

这个 IReportLoadingService 的实现可以有一个 IReportDefinitionRetrievalService 作为依赖,例如

public class ReportLoadingService : IReportLoadingService 
{ 
    private readonly IReportDefinitionRetrievalService _definitionService; 
 
    public ReportLoadingService(IReportDefinitionRetrievalService definitionService) 
    { 
        _definitionService = definitionService; 
    } 
 
    public IReport GetReport(string reportName) 
    { 
        var reportDefinition = definitionService.GetDefinition(reportName); 
        return GenerateReportFromDefinition(reportDefinition); 
    } 
 
    private IReport GenerateReportFromDefinition(string definition) 
    { 
        // Logic to construct an IReport implementation 
    } 
 
} 

IReportDefinitionRetrievalService 的实时实现将访问数据库并返回 XML。现在您的 ReportLoadingService 负责填充 IReport 实例,而另一个服务负责实际获取报告定义。

对于单元测试,您可以创建一个 IReportDefinitionRetrievalService 的 Mock,它可以执行您想要的任何操作(例如,在字典中查找定义)。看看Moq一个好的模拟框架。它将允许你做这样的事情:

[Test] 
public void GetReportUsesDefinitionService() 
{ 
    var mockDefinitionService = new Mock<IReportDefinitionRetrievalService>(); 
    mockDefinitionService.Setup(s => s.GetDefinition("MyReportName")).Returns("MyReportDefinition"); 
 
    var loadingService = new ReportLoadingService(mockDefinitionService.Object); 
 
    var reportInstance = loadingService.GetReport("MyReportName"); 
 
    // Check reportInstance for fields etc 
 
    // Check the definition service was used to load the definition 
    mockDefinitionService.Verify(s => s.GetDefinition("MyReportName"), Times.Once()); 
}