5

我一直在尝试为我的系统中的一组规则实现一个流畅的接口。我想要完成的是这个

TicketRules
.RequireValidation()
.When(quartType => quartType == QuartType.Before).TotalMilageIs(64)
.When(quartType => quartType == QuartType.After).TotalMilageIs(128);

但是,我在实现我打算如何的条件时遇到了麻烦。目前,我需要像在这个片段中那样调用 When() 两次:

rules.When(param => param.Remarque == "Test").TotalMilageIs(100);
rules.When(param => param.Remarque == "Other").TotalMilageIs(50);

var params1 = new AddTicketParameters() { Remarque = "Test" };
var params2 = new AddTicketParameters() { Remarque = "Other" };

rules.ExecuteWith(params1);

Assert.That(ticket.TotalMilage, Is.EqualTo(100));

rules.ExecuteWith(params2);

Assert.That(ticket.TotalMilage, Is.EqualTo(50));

我的 TicketRules 类看起来是这样的:

[EditorBrowsable(EditorBrowsableState.Never)]
public class TicketRules : ITicketRule, IHideObjectMembers
{
    private Ticket theTicket;

    public Ticket Ticket
    {
        set
        {
            theTicket = value;
        }
    }

    private List<ITicketRule> allRules = new List<ITicketRule>();

    public TicketRules()
    {
    }

    public TicketRules(Ticket ticket)
    {
        theTicket = ticket;
    }

    public void Execute()
    {
        ExecuteWith(null, null);
    }

    public void ExecuteWith(AddTicketParameters param)
    {
        ExecuteWith(param, null);
    }

    public virtual void ExecuteWith(AddTicketParameters param, Ticket outsideTicket)
    {
        foreach (ITicketRule rule in allRules)
        {
            rule.ExecuteWith(param, theTicket ?? outsideTicket);
        }
    }

    public TicketRules RequireValidation()
    {
        CreateModifierRule(ticket => ticket.NeedValidation = true);
        return this;
    }

    public TicketRules TotalMilageIs(int milage)
    {
        CreateModifierRule(ticket => ticket.TotalMilage = milage);
        return this;
    }

    private void CreateModifierRule(Action<Ticket> function)
    {
        AddRule(new ModifierTicketRule(function));
    }

    internal void AddRule(ITicketRule rule)
    {
        allRules.Add(rule);
    }

    public WhenClauseTicketRule When(Predicate<AddTicketParameters> predicate)
    {
        WhenClauseTicketRule whenClause = new WhenClauseTicketRule();
        whenClause.Predicate = predicate;

        AddRule(whenClause);

        return whenClause;
    }

    public TicketRules UseStandardFormulaForTotalMilageAndTime()
    {
        AddRule(new StandardFormulaTicketRule());
        return this;
    }

    public TicketRules EnsureMinimumMilageIs(int milage)
    {
        AddRule(new EnsureMinimumMilageTicketRule(milage));
        return this;
    }
}

ITicketRules

internal interface ITicketRule : IHideObjectMembers
{
    void ExecuteWith(AddTicketParameters param, Ticket ticket);
}

我还需要在 When 子句中支持 AddTicketParameters 的子类(尽管我可能对那部分使用了泛型)。我在这里发帖是因为我对我的设计感到困惑,而 Martin Fowler 的文章更让我困惑。

4

1 回答 1

3

这被称为方法链接时的完成问题 试试这个

TicketRules
.RequireValidation()
.When(quartType => quartType == QuartType.Before,
      rule => rule.TotalMilageIs(64))
.When(quartType => quartType == QuartType.After,
      rule => rule.TotalMilageIs(128));

起初它看起来有点奇怪,但它会将您的条件包装到不同的范围内,以便您可以有条件地执行它们。把它想象成创建你自己的 if 块。通过关闭它,您知道何时可以“完成”子语句。

于 2009-07-27T19:15:16.443 回答