所以我正在做一个项目,我从数据库中获取一些数据--有两块数据使这个项目变得很好,一块我有类型(他们称之为事件,但它本质上只是转换成我创建的.NET类型),然后我有XML,我设计了对象,这样它们就可以很好地反序列化了。所有这些都很棒,经过了单元测试,所有的类和方法都遵循单一责任原则。
当我创建工厂来构建业务逻辑来处理我从XML创建的.NET对象时,我的体系结构技能变得模糊了。
基本上这就是我所拥有的。
public class EventProcessorFactory : IEventProcessorFactory
{
private readonly List<IEventProcessor> _eventProcessors;
public EventProcessorFactory()
{
_eventProcessors = new List<IEventProcessor>();
}
public IEventProcessor GetProcessor(Type eventType)
{
var typeOfEventProcessor = GetProcessorFromEventType(eventType);
if (_eventProcessors.Any(x => x.GetType() == typeOfEventProcessor))
return _eventProcessors.Single(x => x.GetType() == typeOfEventProcessor);
var processor = BuildProcessorFromType(typeOfEventProcessor);
_eventProcessors.Add(processor);
return processor;
}
private static Type GetProcessorFromEventType(Type eventType)
{
if (eventType == typeof(EnrollmentEventType))
return typeof(EnrollmentEventProcessor);
if (eventType == typeof(ClaimantAccountInfoEventType))
return typeof(ClaimantAccountInfoEventProcessor);
if (eventType == typeof(PhoneUpdateEventType))
return typeof(PhoneUpdateEventProcessor);
if (eventType == typeof(AddressUpdateEventType))
return typeof(AddressUpdateEventProcessor);
if (eventType == typeof(ClientAccountInfoEventType))
return typeof(ClientAccountInfoEventProcessor);
return null;
}
private IEventProcessor BuildProcessorFromType(Type typeOfEventProcessor)
{
return ((IEventProcessor)Activator.CreateInstance(typeOfEventProcessor));
}
}所以这是可行的,但它看起来相当笨拙。我读过一些关于使用工厂的文章,但是我要么没读对,要么就是没读懂。我对上面的代码有两个问题。
1)如果你添加了一个新的事件,你需要去修改它,我希望以后的开发人员能够只删除"MyCoolNewEventType“和"MyCoolNewEventProcessor”,而不必修改匹配事件到处理器的方法。
2)现在,当我创建一个实例时,我可以只调用.CreateInstance();这很好,因为我没有任何依赖关系,但“事件处理器”可能至少在数据库上有依赖关系。我不是100%确定如何处理它,我不想随机调用Container.Resolve()。
如果有人能指出正确的方向,那将是巨大的。
发布于 2012-10-12 10:11:21
这在某种程度上取决于您希望存储映射的位置,但您可以编写一个自定义配置节:
public class EventProcessorMapping : ConfigurationElement
{
[ConfigurationProperty("event", IsRequired = true)]
public string Event
{
get
{
return this["event"] as string;
}
}
[ConfigurationProperty("processor", IsRequired = true)]
public string Processor
{
get
{
return this["processor"] as string;
}
}
}
[ConfigurationCollection(typeof(EventProcessorMapping), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
public class EventProcessors : ConfigurationElementCollection
{
public EventProcessorMapping this[int index]
{
get
{
return BaseGet(index) as EventProcessorMapping;
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new EventProcessorMapping();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((EventProcessorMapping)element).Event;
}
}
public class RegisterEventProcessorsConfig : ConfigurationSection
{
public static RegisterEventProcessorsConfig GetConfig()
{
return (RegisterEventProcessorsConfig)ConfigurationManager.GetSection("RegisterEventProcessors") ?? new RegisterEventProcessorsConfig();
}
[ConfigurationProperty("EventProcessors")]
public EventProcessors EventProcessors
{
get
{
var o = this["EventProcessors"];
return o as EventProcessors;
}
}
}然后在你的App.config中,你可以拥有:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="RegisterEventProcessors" type="UnitTestProject1.RegisterEventProcessorsConfig, UnitTestProject1"></section>
</configSections>
<RegisterEventProcessors>
<EventProcessors>
<add event="UnitTestProject1.ClaimantAccountInfoEventType, UnitTestProject1" processor="UnitTestProject1.ClaimantAccountInfoEventProcessor, UnitTestProject1" />
<add event="UnitTestProject1.EnrollmentEventType, UnitTestProject1" processor="UnitTestProject1.EnrollmentEventProcessor, UnitTestProject1" />
</EventProcessors>
</RegisterEventProcessors>
</configuration>因此,这至少重新定位了映射配置。至于工厂,如果你不介意处理器类在工厂创建时被实例化,你可以这样做:
public class EventProcessorFactory : IEventProcessorFactory
{
private readonly Dictionary<Type, IEventProcessor> _eventProcessors;
public EventProcessorFactory(IEnumerable<EventProcessorMapping> eventProcessorMappings)
{
_eventProcessors = new Dictionary<Type, IEventProcessor>();
foreach (var mapping in eventProcessorMappings)
{
AddMapping(Type.GetType(mapping.Event), Type.GetType(mapping.Processor));
}
}
public IEventProcessor GetProcessor<T>() where T : IEventType
{
return _eventProcessors[typeof(T)];
}
private void AddMapping(Type eventType, Type processorType)
{
var processor = (IEventProcessor)Activator.CreateInstance(processorType);
_eventProcessors[eventType] = processor;
}
}在构造函数中,我们传入一个映射配置元素的集合,然后立即创建处理器并将其存储在私有集合中。然后,从工厂获取处理器基本上只是一个字典查找。
这两个部分如下所示:
[TestMethod]
public void TestFactory()
{
var config = RegisterEventProcessorsConfig.GetConfig();
var factory = new EventProcessorFactory(config.EventProcessors.Cast<EventProcessorMapping>());
var processor = factory.GetProcessor<EnrollmentEventType>();
Assert.IsInstanceOfType(processor, typeof(EnrollmentEventProcessor));
}发布于 2012-10-12 01:22:02
你要找的是可配置的工厂。它可以使用依赖注入框架来完成,或者是最简单的方式--外部配置(想到xml文件),它将存储您可能实现的列表,并将根据需要进行加载/修改。
使用此解决方案,您将拥有以下内容
<Processors>
<Processor dllname='' classname=''>
....
</Processors>您必须使用反射/ .net提供的任何xml读取技术来加载它。
发布于 2012-10-12 01:35:49
您可以使用reflection并在这些属性中设置处理器类型。
[ProcessorType(typeof(EnrollmentEventProcessor)]
class EnrollmentEvent { ... }简单而干净的解决方案。对于创建的类型,我建议使用Dictionary<Type, Object>来加快访问速度。
https://stackoverflow.com/questions/12845005
复制相似问题