4

J'essaie de mettre en œuvre le modèle de stratégie tout en utilisant le conteneur Windsor. Voici ce que j'ai:Résolution de conteneur basée sur les critères

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

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

Le problème est, comment puis-je configurer mon conteneur (autres exemples de conteneurs bienvenus) d'avoir, pour l'essentiel, les critères de choix de la dépendance appropriée. Donc, si j'enregistrer les informations suivantes

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

comment puis-je utiliser la Commande.destination (adresse) que les critères de la dépendance injectée?

+0

réponse courte: écrire un TaxStrategyFactory –

+0

Hmm - comment voulez-vous fournir le paramètre à l'usine lors de la construction? –

Répondre

6

Voici quelques options, choisissez celle que vous préférez. J'utilise habituellement le premier, c'est le plus 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; } 
    } 
} 
+0

Assez simple, merci Mauricio. J'espérais qu'il y aurait une sorte d'installation de critères à Windsor qui faciliterait la sélection et que je pourrais dépendre de la ITaxStrategy sans l'intermédiaire de l'usine. –

+0

Ce n'est pas possible parce que le conteneur doit connaître l'instance particulière de Order, d'où la solution proxy. Une autre option serait de déplacer l'Ordre dans une sorte de contexte, mais cela compliquerait encore plus les choses. –

+3

Pour ceux qui se tournent vers l'avenir, j'ai mis en place une solution VS 2K8 de poste et d'échantillonnage. http://blog.cromwellhaus.com/index.php/2009/10/strategy-pattern-with-castle-windsor/ –

Questions connexes