如何实现运行时多种策略的使用
我需要处理从服务返回的记录列表。
然而,记录的处理算法会根据记录上的某个字段而完全改变。
为了实现这一点,我定义了一个 IProcessor 接口,它只有一个方法:
public interface IProcessor
{
ICollection<OutputEntity> Process(ICollection<InputEntity>> entities);
}
并且我有两个用于不同类型处理的 IProcessor
具体实现。
问题是我需要同时使用 IProcessor
的所有实现..那么我如何将 IProcessor
注入到我的 Engine 类中来驱动整个事情:
public class Engine
{
public void ProcessRecords(IService service)
{
var records = service.GetRecords();
var type1Records = records.Where(x => x.SomeField== "Type1").ToList();
var type2Records = records.Where(x => x.SomeField== "Type2").ToList();
IProcessor processor1 = new Type1Processor();
processor.Process(type1Records);
IProcessor processor2 = new Type2Processor();
processor.Process(type2Records);
}
}
这这就是我目前正在做的事情..而且它看起来不太漂亮和干净。
关于如何改进这个设计的任何想法..也许使用 IoC?
I need to process a list of records returned from a service.
However the processing algorithm for a record changes completely based on a certain field on the record.
To implement this , I have defined an IProcessor interface which has just one method :
public interface IProcessor
{
ICollection<OutputEntity> Process(ICollection<InputEntity>> entities);
}
And I have two concrete implementations of IProcessor
for the different types of processing.
The issue is that I need to use all implementations of IProcessor
at the same time .. so how do I inject the IProcessor
into my Engine class which drives the whole thing:
public class Engine
{
public void ProcessRecords(IService service)
{
var records = service.GetRecords();
var type1Records = records.Where(x => x.SomeField== "Type1").ToList();
var type2Records = records.Where(x => x.SomeField== "Type2").ToList();
IProcessor processor1 = new Type1Processor();
processor.Process(type1Records);
IProcessor processor2 = new Type2Processor();
processor.Process(type2Records);
}
}
This is what I'm doing at present .. and it doesn't look nice and clean.
Any ideas as to how I could improve this design .. using IoC perhaps ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
更改您的
IProcessor
接口,并添加一个新函数:然后您的代码不需要了解有关实现的任何信息:
您的处理器将发挥作用:
这种方法的好处是您可以加载新处理器来自程序集等,而您的主代码实现不必了解任何单个实现。
Change your
IProcessor
interface, and add a new function:Then your code doesn't need to know anything about the implementation:
Your processor would do the magic:
Benefit of this approach is that you can load new processors from assemblies etc. without your main code implementation having to know about any single implementation out there.
您可以将 SomeField 规范放入 IProcessor 实现中(您必须向 IProcessor 接口添加一个额外的字段),并根据您当前使用的处理器查找相应的记录。
一些代码可以澄清这一点:
或者,您可以在 ProcessRecords 方法中提供 IProcessors,或者将它们设置为 Engine 类中的属性(尽管我更喜欢构造函数注入)。
编辑
您可能还想研究其他答案中的 CanProcess 方法。尽管原理是相同的,但如果您需要更改标准来决定处理器是否应该处理类型,它提供了更具可扩展性/健壮性的解决方案。
You could put the SomeField specification in the IProcessor implementations (you'd have to add an extra field to the IProcessor interface), and find the corresponding records based on the processor you're using at the moment.
A bit of code to clear that up:
Alternatively, you could provide the IProcessors in the ProcessRecords method, or set them as Properties in the Engine class ( though I prefer the constructor injection ).
Edit
You might also want to look into the CanProcess approach in the other answers. Though the principle is the same, it provides an even more extensible/robust solution if you need to change the criteria to decide if the processor should process the types.
就我个人而言,我可能会制作一个 IProcessor 实现来处理不同的记录类型。然后
您可以将所有输入实体传递给 Process 方法,而不必担心它包含哪些记录类型。
此实现缺乏一定的可扩展性,因此如果需要,则必须对其进行扩展(请参阅 Komet 的答案)。基本思想是让一个单独的服务负责选择流程实现。
Personally I would probably make one IProcessor implementation that handles the different record types. Something like
Then you can pass all you input entities to the Process method without worrying which record types it contains.
This implementation lacks some extendability, so if that's needed it has to be extended (see Komet's answer). The basic idea is to have one separate service responsible for choosing process implementation.
这可能看起来有点复杂,但是您可以使用属性来标记处理器,并在运行时读取属性并查看您拥有的处理器并从中构建字典:
This might look a little bit complicated, but you can use attributes to mark your processors, and at runtime read the attributes and see what processor you have and build a dictionary out of it: