【发布时间】:2013-07-05 04:06:16
【问题描述】:
对不起标题。
我有一个系统是面向服务架构的一部分。它接收消息并处理它们。该过程可以简单地归结为将数据从一个位置移动到另一个位置。系统做出的所有决定都可以通过检查系统始终可用的两个不同类来做出:
- 正在处理的消息
- 特定数据操作的配置信息(从哪里移动到哪里等)
这里是主要界面
public interface IComponent
{
bool CanHandle(Message theMessage, Configuration theConfiguration);
int Priority {get;}
}
public interface IComponentLocator<T>
where T : IComponent
{
public LocateComponent(Message theMessage, Configuration theConfiguration);
}
我使用 Castle Windsor 框架解决依赖倒置问题,因此我实现的一个定位器接收通过数组解析器注入的所有适当组件。
这里是:
public class InjectedComponentsLocator<T> : IComponentLocator<T>
where T : IComponent
{
private readonly T[] components;
public InjectedComponentsLocator(T[] components)
{
this.components = components;
this.components.OrderBy((component) => component.Priority);
}
public T LocateComponent(Message theMessage, Configuration theConfiguration)
{
List<T> candidates = this.components.Where((h) => h.CanHandle(message, configuration)).ToList();
if (candidates.Count == 0)
{
throw new Exception(string.Format(Resources.UnableToLocateComponentException, typeof(T).Name));
}
else if (candidates.Count > 1 && candidates[0].Priority == candidates[1].Priority)
{
throw new Exception(string.Format(Resources.AmbiguousComponentException, candidates[0].GetType().Name, candidates[1].GetType().Name));
}
return candidates.First();
}
}
现在问题。 IComponent 接口上的Priority 属性.. 我不喜欢它。实际情况是优先级应该可以通过最具体的IComponent来确定。
例如,假设我有两个组件。
public class HandlesOneRecord : IComponent
{
public bool CanHandle(Message theMessage, Configuration theConfiguration)
{
return theMessage.BatchSize == 1;
}
}
public class HandlesOneInsert : IComponent
{
public bool CanHandle(Message theMessage, Configuration theConfiguration)
{
return theMessage.BatchSize == 1 && theMessage.Action = "Insert";
}
}
我希望系统知道一条记录的插入消息需要选择第二条,因为它是最具体的一条。现在我需要设置不同的优先级,这感觉在创建新组件时会变得笨拙并产生错误。
添加以尝试澄清:
如果系统最终以我设想的方式工作,我将能够拥有两个组件,一个将处理任何“插入”类型的操作,还有一个特定组件将处理批量大小 = 1 的“插入”。任何开发人员写作代码不必关心系统是否选择了正确的,它只会选择正确的。
谢谢!
【问题讨论】:
-
出于好奇,如果您只希望一个组件来处理给定的消息,为什么有多个组件能够处理它?
-
不确定这是否适合你,但也许看看责任链设计模式。一个组件将是起始组件,如果它不能处理该消息,它将把它传递给下一个组件,依此类推。
-
为了找到问题的根源,我过于简单化了,这可能就是为什么感觉做作的原因。至于责任链,我考虑过了。我想不出一种方法,我在链中没有同样的问题,也就是说,确定哪一个是最具体的。
-
app.config 或数据库中的键/值对映射怎么样?关键是组件关心的消息部分。该值将是最负责处理它的类型/组件。然后你可以有一个工厂方法,它使用反射来根据键找到并激活正确的组件。
标签: c# design-patterns castle-windsor soa