在运行时使用配置文件初始化对象
本文关键字:初始化 对象 配置文件 运行时 | 更新日期: 2023-09-27 18:30:03
我目前正在编写一个项目,该项目需要基于XML配置文件生成不同类型的对象。
生成的每个对象都是IProvidor
接口的实例,并且需要包含XML配置文件定义的几个预处理和处理方法。我为生成了不同的工厂类
- 创建提供程序(实现IProvider接口)
- 创建预处理操作(我有所有preProcessor类都需要实现的IPreProcessor接口
- 处理方法也是如此(IHandler接口由几个类实现)
问题
如何在运行时将所有这些组合到一个对象中?
Olivier Jacobt 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(带扩展),但任何容器都可以(尽管每个容器的配置方式不同):
注册:
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() { ... }
}
我将创建一个实现这些接口并注入功能的包装器类。
接口示例
public interface IProvider
{
string ProvideSomething(int id);
}
public interface IPreProcessor
{
void PreProcess(string parameter);
}
public interface IHandler
{
void HandleSomething();
}
包装器将实现所有这些接口
public class ProviderWrapper : IProvider, IPreProcessor, IHandler
{
private IProvider _provider;
private IPreProcessor _preProcessor;
private IHandler _handler;
public ProviderWrapper(IProvider provider, IPreProcessor preProcessor, IHandler handler)
{
_provider = provider;
_preProcessor = preProcessor;
_handler = handler;
}
#region IProvider Members
public string ProvideSomething(int id)
{
return _provider.ProvideSomething(id);
}
#endregion
#region IPreProcessor Members
public void PreProcess(string parameter)
{
_preProcessor.PreProcess(parameter);
}
#endregion
#region IHandler Members
public void HandleSomething()
{
_handler.HandleSomething();
}
#endregion
}
现在,您可以根据配置文件实例化具有所需功能的ProviderWrapper
,并组合不同的接口实现。
var provider = new ProviderWrapper(providerX, preProcessorY, handlerZ);
也许您可以像在运行时一样创建所有这些类的实例,然后将它们序列化为xml。然后,当您想要加载您的"配置"时,只需要反序列化即可。
有关序列化,请参见此处。