2

对不起标题。

我有一个系统,它是面向服务架构的一部分。它接收消息并处理它们。该过程可以简单地归结为将数据从一个位置移动到另一个位置。系统做出的所有决定都可以通过检查系统始终可用的两个不同类来做出:

  1. 正在处理的消息
  2. 特定数据操作的配置信息(从哪里移动到哪里等)

以下是主要接口

    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();
    }
}

现在的问题。界面上的Priority属性IComponent..我不喜欢。现实是优先级应该可以由最具体的来确定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. 任何编写代码的开发人员都不应该关心系统是否选择了正确的代码,它会的。

谢谢!

4

3 回答 3

2

Seeing as your domain is already fairly message-oriented, have you considered using some kind of message bus like NServiceBus?

These types of infrastructure have the message handling pipeline you seem to be looking for, including things like dispatching to handlers based on type, and even with polymorphism as well as the ability to define the order of handlers and for each handler to be able to stop the pipeline.

于 2013-07-08T12:34:32.847 回答
2

您可以通过使用评分系统潜在地做到这一点。

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

IComponent可能看起来像这样:

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 个处理程序,您可以通过为 生成哈希码Message并将成功的查找存储在Dictionary<int, Func<Message, Configuration, Score>>.

于 2013-07-08T12:44:56.037 回答
0

您似乎想根据消息中包含的数据而不是其类型来选择组件。

规范模式可以提供一个不错的、可扩展的选项。您可以拥有 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);
}

在系统的其他部分,您需要:

  • 定义每个具体组件和相关的规范(如果有)。

  • 按特定顺序组装责任链。这可以基于域规则(您可能是唯一知道的)来完成,或者,假设您的所有规范都是互斥的,通过将所有基于规范的组件放在链中的首位。

于 2013-07-08T10:59:33.877 回答