C# 选择最具体的处理程序,而多个处理程序都可以
关于标题,我很抱歉 我有一个系统,它是面向服务体系结构的一部分。它接收并处理消息。这个过程可以简单地归结为将数据从一个位置移动到另一个位置。系统做出的所有决策都可以通过检查系统始终可用的两个不同类别来做出:C# 选择最具体的处理程序,而多个处理程序都可以,c#,design-patterns,castle-windsor,soa,C#,Design Patterns,Castle Windsor,Soa,关于标题,我很抱歉 我有一个系统,它是面向服务体系结构的一部分。它接收并处理消息。这个过程可以简单地归结为将数据从一个位置移动到另一个位置。系统做出的所有决策都可以通过检查系统始终可用的两个不同类别来做出: 正在处理的消息 特定数据操作的配置信息(从何处移动到何处等) 这里是主要的界面 public interface IComponent { bool CanHandle(Message theMessage, Configuration theConfigur
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);
}
我希望系统知道,一条记录的插入消息需要选择第二条,因为它是最具体的一条。现在,我需要设置不同的优先级,这让我感觉在创建新组件时会变得笨拙并产生bug
为试图澄清而添加:如果系统最终按照我设想的方式工作,我将能够有两个组件,一个处理任何“插入”类型的操作,另一个处理batchsize=1的“插入”类型操作的特定组件。任何编写代码的开发人员都不必关心系统是否选择了正确的代码,它会的
谢谢 您似乎希望根据消息中包含的数据而不是其类型来选择组件 这可能是一个不错的、可扩展的选项。正如Bob Horn所建议的那样,您可以拥有一个责任链,其中每个组件将根据注入其中的规范确定是否能够处理消息。大致如下:
public abstract class Component
{
protected Component _next;
protected MessageSpecification _specification;
public Component(MessageSpecification specification)
{
// Inject specification here
}
public void Inspect(Message message)
{
if (_specification.IsSatisfiedBy(message))
{
Handle(message);
}
else _next.Inspect(message);
}
abstract void Handle(Message message);
}
在系统的其他部分,您需要:
- 定义每个混凝土组件和相关规范(如有)
- 按照特定顺序组装责任链。这可以基于域规则(您是唯一可能知道的规则)完成,或者,假设您的所有规范都是互斥的,将所有基于规范的组件放在链的第一位
public abstract class Component
{
protected Component _next;
protected MessageSpecification _specification;
public Component(MessageSpecification specification)
{
// Inject specification here
}
public void Inspect(Message message)
{
if (_specification.IsSatisfiedBy(message))
{
Handle(message);
}
else _next.Inspect(message);
}
abstract void Handle(Message message);
}
在系统的其他部分,您需要:
- 定义每个混凝土组件和相关规范(如有)
- 按照特定顺序组装责任链。这可以基于域规则(您是唯一可能知道的规则)完成,或者,假设您的所有规范都是互斥的,将所有基于规范的组件放在链的第一位
- 鉴于您的域已经相当面向消息,您是否考虑过使用类似的消息总线
这些类型的基础设施具有您似乎正在寻找的消息处理管道,包括基于类型分配给处理程序之类的内容,即使具有多态性以及定义处理程序顺序的能力,并且每个处理程序都能够停止管道。鉴于您的域已经相当面向消息,您是否考虑过使用类似的消息总线
这些类型的基础设施具有您似乎正在寻找的消息处理管道,包括基于类型分配给处理程序之类的内容,即使使用多态性,以及定义处理程序顺序的能力,以及每个处理程序能够停止管道的能力。您也可以通过使用评分系统潜在地做到这一点
public sealed class Score
{
private int _score;
public Score(params bool[] conditions)
{
foreach(bool b in conditions)
{
if(b)
++_score;
else
{
_score = 0;
break;
}
}
} // eo ctor
public int Total { get { return _score; } }
} // eo class Score
您的i组件
可能如下所示:
public interface IComponent
{
Score CanHandle(Message theMessage, Configuration theConfiguration);
} // eo IComponent
专业:
public class HandlesOneRecord : IComponent
{
public Score CanHandle(Message theMessage, Configuration theConfiguration)
{
return new Score(theMessage.BatchSize == 1);
}
}
public class HandlesOneInsert : IComponent
{
public Score CanHandle(Message theMessage, Configuration theConfiguration)
{
return new Score(theMessage.BatchSize == 1, theMessage.Action == "Insert");
}
}
然后,为了找到最合适的处理程序,遍历并选择得分最高的处理程序。如果您有100个处理程序,您可以通过为
消息
生成哈希代码,并将成功的查找存储在字典
中来提高该处理程序的性能。您可以使用评分系统来实现这一点
public sealed class Score
{
private int _score;
public Score(params bool[] conditions)
{
foreach(bool b in conditions)
{
if(b)
++_score;
else
{
_score = 0;
break;
}
}
} // eo ctor
public int Total { get { return _score; } }
} // eo class Score
您的i组件
可能如下所示:
public interface IComponent
{
Score CanHandle(Message theMessage, Configuration theConfiguration);
} // eo IComponent
专业:
public class HandlesOneRecord : IComponent
{
public Score CanHandle(Message theMessage, Configuration theConfiguration)
{
return new Score(theMessage.BatchSize == 1);
}
}
public class HandlesOneInsert : IComponent
{
public Score CanHandle(Message theMessage, Configuration theConfiguration)
{
return new Score(theMessage.BatchSize == 1, theMessage.Action == "Insert");
}
}
然后,为了找到最合适的处理程序,遍历并选择得分最高的处理程序。如果您有100个处理程序,您可以通过为
消息
生成哈希代码,并出于好奇将成功的查找存储在字典
中来提高此处理程序的性能,如果您只希望一个组件处理给定消息,为什么有多个组件能够处理它?不确定这是否适合您,但可以研究责任链设计模式。一个组件将是起始组件,如果它不能处理消息,它将把消息传递给下一个组件,依此类推。我已经大大简化了问题的根源,这可能就是它感觉做作的原因。至于责任链,我考虑过了。我想不出一种方法,我在链中没有同样的问题,那就是确定哪一个是最具体的。那么app.config或数据库中的键/值对映射呢?关键是组件关心的消息部分。该值将是最负责处理它的类型/组件。然后你可以有一个工厂方法,使用反射根据密钥查找并激活正确的组件。出于好奇,如果你只希望一个组件处理给定的消息,为什么有多个组件能够处理它?不确定这是否适合你,但也许可以看看责任链设计模式。一个组件将是起始组件,如果它不能处理消息,它将把消息传递给nex