2009-07-27 2 views
4

저는 시스템에서 규칙 집합에 대한 유창한 인터페이스를 구현하려고했습니다. 내가 성취하려고하는 것은 이것이다.유창한 인터페이스에서 조건부 구현

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

그러나, 내가 의도 한대로 조건을 구현하는 데 어려움이있다. 현재, 나는 때 (2 회이 조각처럼)를 호출해야합니다

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

을 시도 할 때 마무리 문제로 알려져 있지만 조건부을 실행할 수 있도록 다른 범위로 조건문을 래핑한다. 블록에 대한 자신 만의 독창성을 창조하는 것과 같게 생각하십시오. 그것을 닫음으로써 하위 문장을 "마칠"수있을 때를 알 수 있습니다.

+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.TotalMillageIs (128)) 이 경우 그에 대해 어떻게 작동하지 않습니다 하는 경우 (quartType => quartType == QuartType.After, Rule.TotalMilageIs (128)) 그리고를 만들 나중에 적용될 새로운 규칙. 주된 단점은 두 가지 유형의 규칙 인 인스턴스 규칙과 적용된 규칙을 가질 수 있다는 것입니다. 그것들을 함께 고려할 수 있습니다. – Ball

+0

힌트를 보내 주셔서 감사합니다. –