2009-07-27 8 views
4

Ich habe versucht, eine fließende Schnittstelle für eine Reihe von Regeln in meinem System zu implementieren. Was ich versuche zu erreichen, ist diesImplementieren von Bedingungen in einer fließenden Schnittstelle

Allerdings habe ich Probleme bei der Umsetzung der Wenn Bedingung, wie ich sein wollte. Derzeit muss ich in dieser Schnipsel zweimal wie Wenn() aufrufen:

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

Meine TicketRules Klasse sieht folgendermaßen aus:

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

die ITicketRules

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

Ich muss auch die Unterstützung Unterklassen von AddTicketParameters in der When-Klausel (ich habe vielleicht Generics für diesen Teil). Ich poste hier, weil ich in meinem Design total verwirrt bin und der Martin Fowler articles mich noch mehr verwirrt.

+0

Haben Sie diese Implementierung jemals vollständig ausgeführt? Seltsamerweise gibt es nicht wirklich viel zu diesem Thema! Können Sie Ihre Arbeitslösung für dieses Problem posten oder direkt an mich senden? Vielen Dank! –

Antwort

3

Dies wird als Fertig Problem bekannt, wenn method chaining dieses Versuchen

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

Es zunächst ein wenig seltsam aussieht, aber es hüllt Ihren conditionals in einem anderen Bereich, so dass Sie bedingt sie ausführen kann. Denken Sie darüber nach, wie Sie Ihren eigenen Block erstellen. Wenn Sie es schließen, wissen Sie, wann Sie eine Unteranweisung "fertigstellen" können.

+0

Das zweite Argument ist ein Ausdruck Baum richtig? Weil es eine neue Instanz einer Regelklasse erstellen muss. Das Problem ist, ich kann Expression Tree nicht verwenden, da es ein .NET 2.0-Projekt ist. Ich benutze den C# 3.0-Compiler gedacht –

+0

Es ist nur ein Lambda. Wenn Sie nur C# 2.0 verwenden können, versuchen Sie einen anonymen Delegaten http://msdn.microsoft.com/en-us/library/0yw3tz5k(VS.80).aspx Wenn (QuartType => QuartType == QuartType.After, Delegierte (Regel-Regel) {rule.TotalMillageIs (128)) Wenn das nicht funktioniert, wie etwa: Wenn (quartType => quartType == QuartType.After, Rule.TotalMilageIs (128)) Und erstellen neue Regel, die später angewendet wird. Der Hauptnachteil dabei ist, dass Sie zwei Arten von Regeln haben können: Instanzregeln und angewandte Regeln. Sie können sie möglicherweise zusammen faktorisieren. – Ball

+0

Danke für die Hinweise. –

Verwandte Themen