I have been trying to configure Windsor to provide a different implementation for a service depending on which class is being constrcuted:
I have read this http://docs.castleproject.org/Windsor.Registering-components-one-by-one.ashx#Supplying_the_component_for_a_dependency_to_use_Service_override_9
and asked this yesterday Windsor Ioc container: How to register that certain constructors take different implementation of an interface
The answer to that question works correctly when I resolve the class directly, but not when it is in an object graph a few levels deep, and the class I want to override is used as a default implementation of another interface in a different registration
e.g.
I have 2 MVC controllers. One for logging and one for cardpayments. The logging one takes a logging provider which in turn takes an IService
. The CardPaymentController
takes a card payment provider which in turn takes an IService
. The CardPaymentProvider
should get a secure service and the logging provider a normal service
code is below:
Registrations:
Component.For<ILoggingProvider>().ImplementedBy<LoggingProvider>(),
Component.For<ICardPaymentProvider>().ImplementedBy<CardPaymentProvider>(),
Component.For<IService>().ImplementedBy<WebService>().Named("default"),
Component.For<IService>().ImplementedBy<SecureWebService>().Named("secure"),
Component.For<CardPaymentProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),
Component.For<LoggingProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("default"))
Class hierarchy:
public LoggingController(ILoggingProvider loggingProvider)
{
this.loggingProvider = loggingProvider;
}
public CardPaymentController(ICardPaymentProvider cardPaymentProvider)
{
this.cardPaymentProvider = cardPaymentProvider;
}
public interface IService
{
void Doit();
}
public class WebService : IService
{
public void Doit()
{
throw new NotImplementedException();
}
}
public class SecureWebService : IService
{
public void Doit()
{
throw new NotImplementedException();
}
}
public class CardPaymentProvider : ICardPaymentProvider
{
private readonly IService service;
public CardPaymentProvider(IService service)
{
this.service = service;
}
}
public interface ICardPaymentProvider
{
}
public class LoggingProvider : ILoggingProvider
{
private readonly IService service;
public LoggingProvider(IService service)
{
this.service = service;
}
}
public interface ILoggingProvider
{
}
This produces an error on start up:
"There is a component already registered for the given key Spike.CardPaymentProvider"
If I add Named("somename")
to either the CardPaymentProvider
registration or the ICardPaymentProvider
registration, then it starts OK, but doesn't provide a secure implementation of the service to the CardPaymentProvider
- just a normal version.
What am I doing wrong?
You have to define the service overrides in the same registration. Instead of:
Component.For<ICardPaymentProvider>().ImplementedBy<CardPaymentProvider>(),
Component.For<CardPaymentProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),
do:
Component.For<ICardPaymentProvider>()
.ImplementedBy<CardPaymentProvider>()
.ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),