Olivier Jacot-Desc 绝对是在正确的轨道上(+1)。他的回答中唯一缺少的是从配置中加载正确的实现。
有很多方法可以做到这一点,例如将类型名称存储在配置中,但您也可以采用更简单的方法,例如在配置中存储一个简单的布尔值。
IProvider providerX = GetProviderFromConfig();
IHandler handlerZ = GetHandlerFromConfig();
IPreProcessor preProcessorY = GetProcessorFromConfig();
var provider =
new ProviderWrapper(providerX, preProcessorY, handlerZ);
private static IProvider GetProviderFromConfig()
{
if (ConfigurationManager.AppSettings["provider"] == "mail")
{
return new MailProvider();
}
else
{
return new FtpProvider();
}
}
// implement GetHandlerFromConfig just like
// the GetProvider.
更新
当您有许多类型需要切换时,存储类型的名称可能是更好的选择:
private static IProvider GetProviderFromConfig()
{
string typeName =
ConfigurationManager.AppSettings["provider"];
Type providerType = Type.GetType(typeName);
return (IProvider)
Activator.CreateInstance(providerType);
}
更新 2
这是一个如何使用 DI 容器进行配置的示例。我正在使用Simple Injector(与extensions),但任何容器都可以(尽管每个容器的配置方式不同):
注册:
using SimpleInjector;
using SimpleInjector.Extensions;
Type providerType = Type.GetType(
ConfigurationManager.AppSettings["provider"]);
Type handlerType = Type.GetType(
ConfigurationManager.AppSettings["handler"]);
Type processorType = Type.GetType(
ConfigurationManager.AppSettings["preProcessor"]);
var container = new Container();
container.Register(typeof(IProvider), providerType);
container.Register(typeof(IHandler), handlerType);
container.Register(typeof(IPreProcessor), processorType);
解析提供者:
var provider = container.GetInstance<IPovider>();
提示:如果您使用构造函数注入,则不必手动连接类型,容器会为您完成此操作。例如,当您的 MailProvider 看起来像这样时,容器能够通过构造函数注入所需的依赖项(IHandler 和 IPreProcessor):
public class MailProvider : IProvider
{
private readonly IHandler handler;
private readonly IPreProcessor preProcessor;
public MailProvider(IHandler handler,
IPreProcessor preProcessor)
{
this.handler = handler;
this.preProcessor = preProcessor;
}
public void SomeAction() { ... }
}