Here are a few options, pick the one you like best. I usually use the first one, it's the simplest.
[TestFixture]
public class TaxStrategyTests {
[Test]
public void InjectWithFactory() {
var container = new WindsorContainer();
container.AddComponent<USTaxStrategy>();
container.AddComponent<CanadaTaxStrategy>();
container.AddComponent<OrderProcessor>();
container.AddComponent<ITaxStrategyFactory, TaxStrategyFactory>();
var order = new Order {Country = "US"};
container.Resolve<OrderProcessor>().Process(order);
Assert.AreEqual(10, order.Tax);
}
[Test]
public void InjectWithFactoryFromDictionary() {
var container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.AddComponent<USTaxStrategy>();
container.AddComponent<CanadaTaxStrategy>();
container.AddComponent<OrderProcessor>();
container.Register(Component.For<ITaxStrategyFactory>()
.UsingFactoryMethod(kernel => new TaxStrategyFactory2(new Dictionary<string, ITaxStrategy> {
{"US", kernel.Resolve<USTaxStrategy>()},
{"CA", kernel.Resolve<CanadaTaxStrategy>()},
})));
var order = new Order { Country = "US" };
container.Resolve<OrderProcessor>().Process(order);
Assert.AreEqual(10, order.Tax);
}
[Test]
public void InjectWithProxy() {
var container = new WindsorContainer();
container.AddComponent<USTaxStrategy>();
container.AddComponent<CanadaTaxStrategy>();
container.AddComponent<OrderProcessorInterceptor>();
container.AddComponent<ITaxStrategyFactory, TaxStrategyFactory>();
container.Register(Component.For<OrderProcessor2>()
.LifeStyle.Transient
.Interceptors(InterceptorReference.ForType<OrderProcessorInterceptor>()).First);
var order = new Order {Country = "CA"};
container.Resolve<OrderProcessor2>().Process(order);
Assert.AreEqual(5, order.Tax);
}
public class OrderProcessorInterceptor : IInterceptor {
private readonly ITaxStrategyFactory strategyFactory;
public OrderProcessorInterceptor(ITaxStrategyFactory strategyFactory) {
this.strategyFactory = strategyFactory;
}
public void Intercept(IInvocation invocation) {
if (invocation.MethodInvocationTarget.Name == "Process") {
var processor = (OrderProcessor2) invocation.InvocationTarget;
var order = (Order) invocation.Arguments[0];
processor.Strategy = strategyFactory.Create(order);
}
invocation.Proceed();
}
}
public interface IOrderProcessor {
void Process(Order order);
}
public class OrderProcessor2 : IOrderProcessor {
public ITaxStrategy Strategy { get; set; }
public virtual void Process(Order order) {
order.Tax = Strategy.CalcTax(order);
}
}
public class OrderProcessor : IOrderProcessor {
private readonly ITaxStrategyFactory strategyFactory;
public OrderProcessor(ITaxStrategyFactory strategyFactory) {
this.strategyFactory = strategyFactory;
}
public void Process(Order order) {
var strategy = strategyFactory.Create(order);
order.Tax = strategy.CalcTax(order);
}
}
public interface ITaxStrategyFactory {
ITaxStrategy Create(Order o);
}
public class TaxStrategyFactory : ITaxStrategyFactory {
private readonly IKernel kernel;
public TaxStrategyFactory(IKernel kernel) {
this.kernel = kernel;
}
public ITaxStrategy Create(Order o) {
if (o.Country == "US")
return kernel.Resolve<USTaxStrategy>();
return kernel.Resolve<CanadaTaxStrategy>();
}
}
public class TaxStrategyFactory2: ITaxStrategyFactory {
private readonly IDictionary<string, ITaxStrategy> strategies;
public TaxStrategyFactory2(IDictionary<string, ITaxStrategy> strategies) {
this.strategies = strategies;
}
public ITaxStrategy Create(Order o) {
return strategies[o.Country];
}
}
public interface ITaxStrategy {
decimal CalcTax(Order order);
}
public class USTaxStrategy : ITaxStrategy {
public decimal CalcTax(Order order) {
return 10;
}
}
public class CanadaTaxStrategy : ITaxStrategy {
public decimal CalcTax(Order order) {
return 5;
}
}
public class Order {
public string Country { get; set; }
public decimal Tax { get; set; }
}
}