Erfahrung mit fließenden Schnittstellen? Ich brauche deine Meinung!

Diese lange Frage ist leider als Wiki gekennzeichnet, da ich nach etwas frage, das möglicherweise keine sehr konkrete Antwort hat. Wenn es geschlossen ist, soll es so sein.

Meine Hauptfrage lautet:

Wie würden Sie eine fließende Schnittstelle schreiben, die in den Basisklassen nicht vollständig definiert ist, sodass Programme, die die fließenden Schnittstellen verwenden, neue Wörter in der vorhandenen Struktur anheften und dennoch eine Führungsschnittstelle beibehalten können, sodass nach einem Punkt die Intellisense erfolgt? listet nur die Schlüsselwörter auf, die zu diesem Zeitpunkt tatsächlich zutreffen.

Ich bin bei meiner dritten Iteration des Umschreibens meines IoC-Containers. Die zweite Iteration sollte die Leistung verbessern. Diese dritte Iteration soll einige Erweiterbarkeitsprobleme und Trennungsprobleme lösen.

Grundsätzlich besteht das Problem mit der Erweiterbarkeit darin, dass es keine gibt. Ich wollte vor kurzem einen Dienst verwenden, der eine Lebensdauer hatte, und nach Ablauf der Lebensdauer eine neue Kopie auflösen. Lesen Sie beispielsweise jede Minute eine Konfigurationsdatei, jedoch nicht öfter. Dies wurde von meiner aktuellen IoC-Lösung nicht unterstützt, aber die einzige Möglichkeit, es hinzuzufügen, bestand darin, in die Basisklassenbibliothek zu wechseln und dort Unterstützung hinzuzufügen. Das bedeutet für mich, dass ich keine erweiterbare Klassenbibliothek erstellt habe. Um ehrlich zu sein, wollte ich keine Erweiterbarkeit einbauen, aber dann wusste ich nicht genau, wie viel Schmerz es bedeuten würde, später so etwas hinzuzufügen.

Ich schaue auf meine flüssige Benutzeroberfläche für die Konfiguration, und da ich auch die volle Erweiterbarkeit in die Benutzeroberfläche einbauen möchte (oder sie loswerden möchte, was ich nicht gerne mache), muss ich die Dinge anders machen.

Als solches brauche ich deine Meinung. Ich habe nur sehr wenig Erfahrung mit fließenden Interfaces, aber ich habe eine Menge Code gesehen, der sie verwendet, und als solcher gibt es einen offensichtlichen Vorteil, der sofort greift:

Code, der fließende Schnittstellen verwendet, ist normalerweise sehr einfach zu lesen

Mit anderen Worten:

ServiceContainer.Register<ISomeService>()
    .From.ConcreteType<SomeService>()
    .For.Policy("DEBUG")
    .With.Scope.Container()
    .And.With.Parameters
        .Add<String>("connectionString", "Provider=....")
        .Add<Boolean>("optimizeSql", true);

ist leichter zu lesen als dies:

ServiceContainer.Register(typeof(ISomeService), typeof(SomeService),
    "DEBUG", ServiceScope.Container, new Object[] { "Provider=...", true });

Lesbarkeit ist also ein Problem.

Die Programmiererführung ist jedoch eine andere, die beim Lesen von vorhandenem Code, im Internet oder in einem Editor nicht einfach zu verstehen ist.

Grundsätzlich, wenn ich das tippe:

ServiceContainer.Register<ISomeService>()
    .From.|
          ^-cursor here

und dann zeigt Intellisense die verfügbaren Auflösungsarten an. Nachdem ich diesen ausgewählt habe und schreibe:

ServiceContainer.Register<ISomeService>()
    .From.ConcreteType<SomeService>()
    .For.|

dann bekomme ich erst nach dem Schlüsselwort "For" Dinge zur Verfügung, wie "Policy" und so.

Ist dies jedoch ein großes Problem? Haben Sie so flüssige Schnittstellen verwendet? Das offensichtliche Problem beim Definieren der Schnittstelle besteht darin, eine Klasse oder eine Schnittstelle mit allen Schlüsselwörtern und allem zu erstellen, sodass die Intellisense nach jedem Komma alles enthält. Dies könnte jedoch auch dazu führen, dass dies legal ist (wie in kompiliert) Code:

ServiceContainer.Register<ISomeService>()
    .From.ConcreteType<SomeService>()
    .From.Delegate(() => new SomeService())
    .From.With.For.Policy("Test");

Daher möchte ich die fließenden Benutzeroberflächen so strukturieren, dass sie nach Ihren Angaben angezeigt werdenWie Um einen Dienst aufzulösen, können Sie das nicht noch einmal tun.

Mit anderen Worten, fließende Benutzeroberflächen sind sehr einfach zu verwenden, da sie Sie zu dem führen, was Sie tun können.

Aber ist das typisch? Da ich in der Lage sein möchte, eine Reihe dieser Schlüsselwörter, wie den Typ des Resolvers (ConcreteType, Delegate usw.), den Typ des Gültigkeitsbereichs (Factory, Container, Singleton, Cache usw.) als Erweiterungsmethoden hinzuzufügen, damit Programme können ihre eigenen Methoden definieren, um dies zu tun, ohne die Basisklassen ändern zu müssen. Das bedeutet, dass ich Schnittstellen für alle Zwischenhalte bereitstellen und die eigentlichen wichtigen Schlüsselwörter verwenden muss. Die Implementierung für diese Schlüsselwörter muss dann eine Zwischenstopp-Schnittstelle auswählen, um sie gegebenenfalls zurückzugeben.

Es sieht also so aus, als müsste ich eine Schnittstelle definieren für:

xyz.Von.xyz.From.<Resolver here>.<Resolver here>.With.<Resolver here>.For.

usw. aber das sieht für mich fragmentiert aus.

Kann jemand, der Erfahrung mit fließenden Schnittstellen hat, meine zitierte Antwort oben lesen und versuchen, mir eine kurze Antwort zu geben?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage