我正在尝试解析依赖于我正在调用的操作中的参数值的依赖项。
我有这个WCF服务
public class InformationService : IInformationService
{
private readonly IValueProvider _valueProvider;
public InformationService(IValueProvider valueProvider)
{
_valueProvider= valueProvider;
}
public CompanyReportResponse CompanyReport(string option)
{
_valueProvider.Execute(option);
}
}
我还在容器中为我的ValueProvider注册了两个具体类型。
Registry.For<IValueProvider>().Add<ValueProvider1>().Named("No1");
Registry.For<IValueProvider>().Add<ValueProvider2>().Named("No2");
根据选项的价值,是否可以使用不同的Value Provider?
即,当选项为"value1"
时,_valueProvider
将使用具体类型ValueProvider1
,当选项为"value2
时,则_valueProvider
将使用具体类型ValueProvider2
。
答案 0 :(得分:2)
我看到至少2种不同的选择。
如果ValueProvider
仅用于该方法,则可以考虑方法注入。由于在传递option
参数时您已经知道将要使用哪一个,因此您可以提供IValueProvider的实现作为附加参数。
public CompanyReportResponse CompanyReport(string option, IValueProvider provider)
{
_provider.Execute(option);
}
第二个选项是定义一个工厂来构建你的ValueProvider,并通过构造函数注入注入这个工厂。工厂将有一个方法来根据option
参数实例化正确的ValueProvider。
public interface IValueProviderFactory
{
IValueProvider CreateProvider(string option);
}
public class ValueProviderFactory : IValueProviderFactory
{
public IValueProvider CreateProvider(string option)
{
// Insert custom instantiation logic here:
// if option == "value1" return ValueProvider1 and so on
}
}
public class InformationService : IInformationService
{
private readonly IValueProviderFactory _valueProviderFactory;
public InformationService(IValueProviderFactory valueProviderFactory)
{
_valueProviderFactory = valueProviderFactory;
}
public CompanyReportResponse CompanyReport(string option)
{
var valueProvider = _valueProviderFactory.CreateProvider(option);
valueProvider.Execute(option);
}
}
答案 1 :(得分:2)
+1 @ filpen的回答。我想添加第三个选项。您可以引入代理到正确实现的代理,而不是注入工厂或执行基于上下文的注入:
public SwitchingValueProviderProxy: IValueProvider
{
private readonly ValueProvider1 provider1;
private readonly ValueProvider2 provider2;
public SwitchingValueProviderProxy(
ValueProvider1 provider1,
ValueProvider2 provider2)
{
this.provider1 = provider1;
this.provider2 = provider2;
}
void IValueProvider.Execute(option option)
{
this.GetProvider(option).Execute(option);
}
private IValueProvider GetProvider(string option)
{
// custom instance logic here
if (option.EndsWith("1"))
return this.provider1;
if (option.EndsWith("2"))
return this.provider2;
throw InvalidOperationException();
}
}
这有一些明显的优势。首先,这完全隐藏了工厂和确定从客户端执行哪个提供程序的逻辑。客户端现在仅依赖于IValueProvider
接口。接下来,配置现在变得非常干净:
Registry.For<IValueProvider>()
.Add<SwitchingValueProviderProxy>();
就是这样。如果您仍然可以将选择逻辑提取到IValueProviderFactory
并将其注入SwitchingValueProviderProxy
,这将使该类简单且集中,并且仍然使应用程序的其余部分对工厂一无所知。 / p>