我目前正在编写一个需要根据XML配置文件生成不同类型对象的项目。
生成的每个对象都是IProvidor
接口的实例,并且需要包含多个预处理和处理XML配置文件定义的方法。
我为:
问题
如何在运行时将所有这些组合成一个对象?
答案 0 :(得分:3)
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 Container配置它的示例。我正在使用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() { ... }
}
答案 1 :(得分:2)
我会创建一个包装器类来实现这些接口并注入功能。
示例接口
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);
答案 2 :(得分:0)
也许您可以像在运行时一样创建所有这些类的实例,然后将它们序列化为xml。然后,当您想要加载“配置”时,您只需要反序列化。
请参阅here了解序列化。