Pregunta

Estoy tratando de implementar el patrón de Estrategia mientras uso el contenedor Windsor. Esto es lo que tengo:

public class OrderProcessor {
...
    public OrderProcessor(ITaxStrategy strategy) {}

    public void Process(Order order)
    { 
      order.Tax = strategy.CalcTax(order);
    }
}

El problema es cómo configuro mi contenedor (otros ejemplos de contenedores son bienvenidos) para tener, esencialmente, criterios para elegir la dependencia adecuada. Entonces, si registro lo siguiente

public class USTaxStrategy : ITaxStrategy { ... }
public class CanadaTaxStrateg : ITaxStrategy { ... }

¿cómo uso el Order.Destination (dirección) como criterio para la dependencia inyectada?

¿Fue útil?

Solución

Aquí hay algunas opciones, elija la que más le guste. Usualmente uso el primero, es el más simple.

[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; }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top