2012-04-14 6 views
1

Ich versuche, eine DSL zu schreibenDesigning Fluent Interface-Methoden

Ich habe Methoden, die Strings zurückgeben, aber wenn ich die Saiten kombinieren möchte ich brauche ein + Symbol zu verwenden, aber ich würde die Methoden wie zusammen nennen, aber ich ist nicht sicher, wie es

ich habe Methoden zur Zeit zu erreichen, wie

MyStaticClass.Root() MyStaticClass.And() MyStaticClass.AnyInt() der Strings zurückgeben

ich mag wäre in der Lage sein, zu tun

Root().And().AnyInt() die zu einer Zeichenfolge führen

Antwort

1

Die Methoden sollten eine Wrapper-Klasse zurückgeben. Die Methoden sind auch Instanzmethoden der Wrapper-Klasse. Beispiel:

class Fluent 
{ 
    private string _value; 
    public Fluent And() 
    { 
     this._value += "whatever"; 
     return this; 
    } 
    public Fluent AnyInt() 
    { 
     this._value += "42"; 
     return this; 
    } 
    public override string ToString() { return _value; } 
} 

Sie könnten auch eine implizite oder explizite Konvertierung von Fluent zu bespannen, anstatt (oder zusätzlich zu) der ToString() Überschreibung definieren.

Auch für Produktionscode würde ich einen String-Builder verwenden, um viele Anrufe zu vermeiden Concat.

+0

String Builder Append? Wie würde eine implizite Umwandlung aussehen, um das Ergebnis zu erhalten? Ist dieser Thread auch sicher? – Jon

+1

'public static implizite Operatorzeichenfolge (Fluent f) {return f.ToString(); } '. Siehe http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx –

+0

@Jon, es sei denn, Sie planen, die gleiche Instanz aus mehreren Threads zu verwenden, Thread-Sicherheit ist kein Problem, um das Sie sich kümmern sollten. Fließende Schnittstellen werden normalerweise in einer einzigen Methode verwendet und dann verworfen. –

3

Sie brauchen nicht + Symbol zu verwenden. Verwenden StringBuilderhttp://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx

Beispiel

StringBuilder builder = new StringBuilder(); 
builder.Append("One string ").Append("Second string").Append("Another string"); 
string final = builder.ToString(); 

Wenn Sie eine einfache benutzerdefinierte wollen Fluent Interface verwenden Sie die folgenden Schritte aus:

public class MyOwnStringBuilder 
{ 
    public StringBuilder Builder; 


    public MyOwnStringBuilder() 
    { 
     this.Builder = new StringBuilder(); 
    } 

    public static MyOwnStringBuilder Root 
    { 
    get{return new MyOwnStringBuilder();} 
    } 

    public string End 
    { 
    get{return Builder.ToString();} 
    } 

    public MyOwnStringBuilder And(string value) 
    { 
    Builder.Append(value); 
    return this; 
    } 

    public MyOwnStringBuilder AnyInt(string value) 
    { 
     Builder.Append(value); 
     return this; 
    } 
} 

Sie würden es verwenden:

MyOwnStringBuilder.Root 
     .And("some value") 
     .AnyInt("some new value") 
     .End; 

Grüße.

+0

Sie müssten immer noch Ende anrufen? Auch das ist für eine Web-App so ist es threadsicher. Nicht sicher, wie Statik für die Fadensicherheit funktioniert – Jon

+0

Schöne Antwort; Ich würde die Klasse jedoch umbenennen :-) – phoog

+0

ja solltest du End nennen, und es gibt keine Probleme mit Thread-Sicherheit. @phoog Ich habe es nach dem vorgeschlagenen in der Frage benannt, aber ja, es wäre besser, es umzubenennen. –