2009-07-27 2 views
4

Я пытался внедрить свободный интерфейс для набора правил в моей системе. То, что я пытаюсь выполнить, - этоВыполнение условного в свободном интерфейсе

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

Однако у меня возникли проблемы с внедрением When when condition, каким я должен был быть. В настоящее время, мне нужно позвонить Когда() дважды, как в этом фрагменте кода:

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

Я также должен поддерживать подклассы AddTicketParameters в предложении When (возможно, я, возможно, использовал дженерики для этой части). Я размещаю здесь, потому что меня все путают в моем дизайне, и Мартин Фаулер articles путают меня еще больше.

+0

Вы когда-нибудь получали эту реализацию полностью? Как ни странно, на этой теме не так много всего! Можете ли вы опубликовать свое рабочее решение по этой проблеме или отправить его мне непосредственно? Благодаря! –

ответ

3

Это известно как проблема отделочного когда method chaining Попробуйте

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

Это выглядит немного странно на первый, но это оборачивает ваши условными в другой области, так что вы можете выполнять их условно. Подумайте об этом, как о создании своего собственного блока if. Закрывая его, вы знаете, когда можете «закончить» подзаголовок.

+0

Второй аргумент - это дерево выражений? Потому что ему нужно создать новый экземпляр класса правил. Проблема заключается в том, что я не могу использовать дерево выражений, потому что это проект .NET 2.0. Я использую компилятор C# 3.0. –

+0

Это просто лямбда. Если вы можете использовать только C# 2.0, попробуйте анонимный делегат http://msdn.microsoft.com/en-us/library/0yw3tz5k(VS.80).aspx Когда (quartType => quartType == QuartType.After, делегат (правило Rule) {rule.TotalMillageIs (128)) Если это не работает, как насчет: Когда (quartType => quartType == QuartType.After, Rule.TotalMilageIs (128)) И создать новое правило, которое будет применяться позднее. Главным недостатком этого может быть два типа правил, правила экземпляра и применяемые правила. Возможно, вы сможете скомпоновать их вместе. – Ball

+0

Спасибо за подсказки. –

Смежные вопросы