2012-12-26 11 views
8

Gelegentlich finde ich mich in einer Situation, in der ich einen Dienst nur auflösen muss, wenn eine bestimmte Bedingung erfüllt ist. Beispielsweise könnte ein Benutzer auswählen, eine E-Mail oder eine SMS-Benachrichtigung zu senden. Ich würde gerne den E-Mail- oder SMS-Dienst laden, je nachdem, was der Benutzer wählt, so dass ich nicht beide laden muss und Ressourcen verschwenden muss (was wäre, wenn es zum Beispiel 10 Optionen für den Benutzer gäbe ...?).Castle Windsor Lazy Load-Dienste

Das Problem, das ich habe, ist mit der Verwendung des Containers außerhalb meines Bootstrap-Codes (ich möchte nicht, dass mein Code von diesem Container abhängig ist). Ich kann anscheinend keinen Weg finden, den Container für Lazy-Loading-Dienste zu verwenden (es sei denn, ich erstelle die benötigten Dienste manuell und mache alle DI manuell). Ist dies eine Situation, in der die Regeln verbogen werden können oder gibt es einen besseren Weg?

Antwort

5

Wenn Sie Castle Windsor 3.0 oder neuer verwenden, können Sie eine faule Auflösung verwenden.

Siehe What's new in Windsor 3 for more details.

Registrierungsprozess ändert sich ein wenig (neuer Komponentenlader muss registriert werden).

Danach registrieren Sie nur Komponenten wie immer, aber lösen Abhängigkeiten als Lazy<T> statt T. Bis Sie nicht auf .Value Eigentum Ihrer Lazy<T> zugreifen, wird die Abhängigkeit nicht gelöst werden, so dass Sie einige träge ausgewertete Objekte übergeben können und nur auf die, die Sie benötigen und wann Sie benötigen.

Wenn Sie mehr Optionen für den Benutzer haben, sollten Sie vielleicht eine abstrakte Factory-Schnittstelle erstellen. Sie würden dann nur diese Fabrik registrieren und auflösen, und die Fabrik selbst würde einen geeigneten Dienst zum Senden von Benachrichtigungen erstellen (sei es eine Mail, eine SMS oder eine andere Option). Implementierung der Fabrik kann von Hand oder Schloss Windsor können Sie damit (ich denke von Version 3.0) codiert werden.

Oft wenn ich solche Fabrik verwenden, implementiere ich es von Hand und übergeben Container als Abhängigkeit, so dass nur die Fabrik-Implementierung von meinem Container abhängt.

1

Im Allgemeinen können Sie das mit der Typed Factory Facility tun.

Auf den Punkt gebracht, wenn Sie die Komponente lösen, die diese Dienste nutzt, anstatt sie eine E-Mail oder SMS-Service geben, geben sie Ihnen eine Fabrik, die sie erstellen können (die von Ihnen festgelegt wird, ohne Verweise auf die Container)

Die Einrichtung kümmert sich um die "Implementierung" Ihrer Fabrik (von der Schnittstelle, die Sie erstellen), so dass es sehr wenig zu tun gibt.

+0

Was passiert, wenn Jeder meiner Dienste hat seine eigenen Abhängigkeiten. Zum Beispiel hat der SMS-Dienst 3 eindeutige Abhängigkeiten, der E-Mail-Dienst hat 4 eindeutige Abhängigkeiten usw. Würde ich nur 20 (oder wie viele es gibt) Abhängigkeiten in die Fabrik einspeisen? Große Antwort übrigens. – orourkedd

+0

Die Fabrik wird von Schloss umgesetzt. Sie konfigurieren Ihre Dienste wie gewohnt. –

2

Nur ein Beispiel zu vereinfachen (basierend auf Marcin Deptuła Antwort)

// activate Lazy initialization feature for all Components 
.Register(Component.For<ILazyComponentLoader>().ImplementedBy<LazyOfTComponentLoader>())  
// register rest of component(s) 
.Register(Component.For<IIssueRepository>().ImplementedBy<IssueRepository>()) 
. .... 

resolve lazily (Eigenschaft Injektion)

public Lazy<IIssueRepository> IssueRepository { get; set; } 
IssueRepository.Value.GetLastIssue(); 

resolve normal (Eigenschaft Injektion)

public IIssueRepository IssueRepository { get; set; } 
IssueRepository.GetLastIssue();