I have 2 implementations of the same interface and want to use implementation1 if the user is logged in or implementation2 if the user is not logged in. How can I configure this with castle windsor?
2 Answers
You could add a handler selector, which would be able to select between available implementations depending on e.g. whether Thread.CurrentPrincipal
was set (or HttpContext.Current.Request.IsAuthenticated
in ASP.NET/MVC if I remember correctly).
The handler selector would probably look somewhat like this:
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; }
}
// ....
}
Only downside of handler selectors is that they're not pulled from the container - i.e. they're added as an instance to the container at registration time, so they don't get to have dependencies injected, lifestyle managed, etc., but there are ways to mitigate that - take a look at F.T.Windsor if you're interested in seeing how that can be done.

- 18,258
- 2
- 39
- 63
-
1wondering if with 3.0 version anything changed - I mean if it is still needed external facility. – Giedrius Nov 16 '12 at 13:55
-
The "handler selector" link is obsolete. The actual one is: https://github.com/castleproject/Windsor/blob/master/docs/handler-selectors.md – cly Mar 27 '23 at 08:49
One way to solve this would be, Register the service with key and then resolve as you need.
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;
}
}
The registration:
container.Register(Component.For<ISample>().ImplementedBy<SampleA>().Named("SampleA").LifeStyle.Transient);
container.Register(Component.For<ISample>().ImplementedBy<SampleB>().Named("SampleB").LifeStyle.Transient);
// Resolve when SampleA needed.
var sampleA = container.Resolve<ISample>("SampleA");
// Resolve when SampleB needed.
var sampleB = container.Resolve<ISample>("SampleB");

- 963
- 8
- 14
-
There is no way windsor will know user is logged in or not unless you alter/extend it's internal implementation. There can be a Decider class in between which will take 'log in factor' in account and give the desired implementation. – Shuhel Ahmed Sep 21 '11 at 20:20
-
Windsor *does* have mechanisms for this (see mookid's answer), it's not necessary to alter its internal implementation at all. – Mauricio Scheffer Sep 21 '11 at 20:46
-
Thanks, I meant to say extend not 'alter'. +1 for mookids's answeer. – Shuhel Ahmed Sep 21 '11 at 21:34
-
1As long as [Static service locator is not good idea](http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx), you can use this solution only if you have access to container - and usually you don't. – Giedrius Nov 16 '12 at 13:52