我正在编写一个简单的控制台应用程序,负责连接数据库,从中选择特定的产品(基于提供的条件),并使用此产品进行一些处理。我将命令行参数存储到此类的一个实例中:构造函数注入和注入依赖关系的初始化
public class Arguments
{
public string ConnectionString { get; set; }
public int ProductId { get; set; }
public string ProductName { get; set; }
}
在某些时候,我需要从数据库中获取产品。我使用下面库为:
public interface IProductRepository
{
Product GetById(int productId, string connectionString);
Product GetByName(string productName, string connectionString);
}
然后,我注入库来使用它的类,如实现:这是工作
public class ProductProcessor
{
private readonly IProductRepository productRepository;
public ProductProcessor(IProductRepository productRepository)
{
this.productRepository = productRepository;
}
public void Process(Arguments arguments)
{
Product productToProcess;
if (!string.IsNullOrEmpty(arguments.ProductName))
{
productToProcess = productRepository.GetByName(arguments.ProductName, arguments.ConnectionString);
}
else
{
productToProcess = productRepository.GetById(arguments.ProductId, arguments.ConnectionString);
}
// ....
}
}
,但什么我不t喜欢的设计是IProductRepository
的每种方法都有一个connectionString
参数。如果没有涉及依赖注入,我可能会重写它,如下所示:
public void Process(Arguments arguments)
{
Product productToProcess;
ProductRepository productRepository = new ProductRepository(arguments.ConnectionString);
if (!string.IsNullOrEmpty(arguments.ProductName))
{
productToProcess = productRepository.GetByName(arguments.ProductName);
}
else
{
productToProcess = productRepository.GetById(arguments.ProductId);
}
// ....
}
这使我能够拥有更简单,更易于使用的界面。当然,现在ProductRepository
没有无参数构造函数,并且很难与DI容器一起使用。理想情况下,我希望两全其美,即用构造函数中的连接字符串初始化ProductRepository
,并从其方法中删除连接字符串。 实现此目标的最佳方法是什么?
一些方法我已经考虑:
- 添加的方法
Initialize(string connectionString)
到IProductRepository
将基本上作为一个构造函数。明显的缺点是我现在需要检查Initialize
是否在执行GetById
或GetByName
方法之前被调用。 - 请勿使用构造函数注入并使用服务定位器模式来实例化
ProductRepository
。我不太喜欢Service Locator,但这可能只是可能的解决方案。
有没有更好的选择?
编辑:从答案中我看到我应该发布更多的上下文。我正在使用Ninject作为我的DI容器。在我的Program.cs Main
方法,我注册所有依赖于容器和实例化作为一个入口点到应用程序的类:
public static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel();
kernel.Bind<IArgumentsParser>().To<IArgumentsParser>();
kernel.Bind<IProductProcessor>().To<ProductProcessor>();
kernel.Bind<IProductRepository>().To<ProductRepository>();
MainClass mainClass = kernel.Get<MainClass>();
mainClass.Start(args);
}
的MainClass
如下所示:
public class MainClass
{
private readonly IArgumentsParser argumentsParser;
private readonly IProductProcessor productProcessor;
public MainClass(IArgumentsParser parser, IProductProcessor processor)
{
argumentsParser = parser;
productProcessor = processor;
}
public void Start(string[] args)
{
Arguments parsedArguments = argumentsParser.Parse(args);
productProcessor.Process(parsedArguments);
}
}
这使我可以对Ninject有一个依赖关系,并只在一个地方创建整个图形(Main
方法),其余应用程序对DI和容器一无所知。
如果可能的话,我想保留它。
是不是连接字符串泄漏抽象?你已经在你的书中陈述了这一点。也许,在这种情况下(连接字符串作为用户输入),这不是很明确吗? – mnn
是的,你可以争辩说,但我只是使用OP的对象模型的那部分,以便不会一下子搞乱所有东西:) –