Ich habe 2 Implementierungen des gleichen Interfaces und möchte Implementierung 1 verwenden, wenn der Benutzer angemeldet ist, oder Implementierung 2, wenn der Benutzer nicht angemeldet ist. Wie kann ich dies mit Castle Windsor konfigurieren?
Antworten
Zu viele Anzeigen?Sie könnten einen Handler Selector hinzufügen, der in der Lage wäre, zwischen verfügbaren Implementierungen zu wählen, abhängig davon, ob z.B. Thread.CurrentPrincipal
festgelegt war (oder HttpContext.Current.Request.IsAuthenticated
in ASP.NET/MVC, wenn ich mich richtig erinnere).
Der Handler Selector würde wahrscheinlich ungefähr so aussehen:
public class MyAuthHandlerSelector : IHandlerSelector
{
public bool HasOpinionAbout(string key, Type service)
{
return service == typeof(ITheServiceICareAbout);
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
return IsAuthenticated
? FindHandlerForAuthenticatedUser(handlers)
: FindGuestHandler(handlers);
}
bool IsAuthenticated
{
get { return Thread.CurrentPrincipal != null; }
}
// ....
}
Der einzige Nachteil von Handler Selectors ist, dass sie nicht aus dem Container aufgerufen werden - d.h. sie werden als Instanz zum Container zur Registrierungszeit hinzugefügt, sodass sie keine abhängigen Injektionen, Lifestyle-Verwaltung usw. erhalten, aber es gibt Möglichkeiten, das zu umgehen - schauen Sie sich F.T.Windsor an, wenn Sie daran interessiert sind zu sehen, wie das gemacht werden kann.
Ein Weg, dies zu lösen wäre, den Dienst mit einem Schlüssel zu registrieren und dann bei Bedarf aufzulösen.
public interface ISample
{
int Calculate(int a, int b);
}
class SampleB : ISample
{
public int Calculate(int a, int b)
{
return a + b + 10;
}
}
class SampleA : ISample
{
public int Calculate(int a, int b)
{
return a + b;
}
}
Die Registrierung:
container.Register(Component.For().ImplementedBy().Named("SampleA").LifeStyle.Transient);
container.Register(Component.For().ImplementedBy().Named("SampleB").LifeStyle.Transient);
// Auflösen, wenn SampleA benötigt wird.
var sampleA = container.Resolve("SampleA");
// Auflösen, wenn SampleB benötigt wird.
var sampleB = container.Resolve("SampleB");