I am trying to implement a free interface for a set of rules in my system. What I'm trying to accomplish is
TicketRules .RequireValidation() .When(quartType => quartType == QuartType.Before).TotalMilageIs(64) .When(quartType => quartType == QuartType.After).TotalMilageIs(128);
However, I am having problems implementing When when condition, which I actually was. Currently I need to call When () twice, as in this snippet:
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));
The TicketRules class is as follows:
[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); }
I also need to support subclasses of AddTicketParameters in the When clause (maybe I'm using generics for this part). I post here because everything confuses me in my design, and Martin Fowler 's articles confuse me even more.
source share