【发布时间】:2018-04-19 05:49:03
【问题描述】:
我想让我的类的调用者能够按名称选择提供者,而不是像标准 DI 推荐的那样传递提供者具体类。它将允许对客户端隐藏实际的实现细节,仍然可以控制使用哪个提供者。我们通过实现工厂来做到这一点
public ICurrencyProvider GetCurrencyServiceProvider(string providerName)
{
switch (providerName)
{
case "CurrencyLayerAPI":
{ currencyService = new CurrencyLayerWrapper(); }
break;
case "XE":
{ currencyProvider = new XEWrapper(); }
break;
}
return _currencyProvider;
}
并且构造函数期望 providerName 作为参数。
但是对于单元测试,我希望使用替代,而不是提供者的具体类。 我最终得到了 2 个参数,它们负责相同的选择——生产代码的名称和测试调用的接口。
public CurrencyProcessor(string providerName, ICurrencyProvider substituteCurrencyProvider =null)
{
if(!providerName .IsNullOrEmpty())
{
_currencyProvider = GetCurrencyServiceProvider(providerName);
}
else
{ _currencyProvider =substituteCurrencyProvider;
}
}
另一种实现方式是从配置中读取 providerName,而不是将其作为参数传递。
public CurrencyProcessor(IConfigurationProvider configurationProvider, ICurrencyProvider substituteCurrencyProvider =null)
{
_providerName = _configurationProvider.GetAppSetting("CurrencyProviderToUse");
if(!providerName .IsNullOrEmpty())
{
_currencyProvider = GetCurrencyServiceProvider(providerName);
}
else
{ _currencyProvider =substituteCurrencyProvider;
}
}
我徘徊,是否存在更好的方法来使用单个参数来控制内部对象的创建,但避免将创建对象的责任交给客户端。
相关讨论
How to use Dependency Injection without breaking encapsulation?
Preferable way of making code testable: Dependency injection vs encapsulation
https://softwareengineering.stackexchange.com/questions/344442/dependency-injection-with-default-construction
【问题讨论】:
-
你要么必须注入工厂,要么注入
ICurrencyProvider而不是你在这里做的事情 -
鉴于您的构造函数正在调用工厂,我建议您只注入 ICurrencyProvider
-
@KeithNicholas:注入 ICurrencyProvider 期望调用者负责创建具体的 CurrencyProvider 实现,我希望避免这种情况。不确定如何注入工厂?
-
它已经通过传递一个“字符串”来负责,一个表示类型的字符串,最好使用类型
标签: c# unit-testing dependency-injection encapsulation factory-pattern