4

Windsor 컨테이너를 사용하는 동안 전략 패턴을 구현하려고합니다.컨테이너 기준에 따라 결정

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

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

문제는, 어떻게 내 컨테이너 (다른 컨테이너 예 환영) 가지고를 구성 할 본질적으로, 적절한 의존성을 선택하는 기준 : 여기에 내가 가진 것입니다. 나는 다음과 같은

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

를 등록 그렇다면 어떻게 주입 된 의존성에 대한 기준과 Order.Destination (주소)를 사용합니까?

+0

짧은 답변 : TaxStrategyFactory 작성 –

+0

흠 - 건설 중 매개 변수를 어떻게 제공 하시겠습니까? –

답변

6

몇 가지 옵션이 있습니다. 가장 좋아하는 것을 선택하십시오. 나는 보통 첫 번째 것을 사용합니다. 가장 간단합니다.

[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; } 
    } 
} 
+0

간단합니다. 감사합니다. Mauricio. 나는 윈저에 어떤 종류의 기준 시설이있어서 (선택의 용이성을 높이고) 공장 중매인이 아닌 ITaxStrategy에 의존 할 수 있기를 바랬다. –

+0

컨테이너가 특정 Order 인스턴스, 즉 프록시 솔루션에 대해 알아야하기 때문에 불가능합니다. 또 다른 선택은 상황을 일종의 상황으로 옮기는 것이지만, 그것은 일을 더욱 복잡하게 할 것입니다. –

+3

미래를 보러 오는 사람들에게 게시 및 샘플 VS 2K8 솔루션을 함께 제공합니다. http://blog.cromwellhaus.com/index.php/2009/10/strategy-pattern-with-castle-windsor/ –

관련 문제