Dependency injection 基于条件的容器解析
我试图在使用Windsor容器时实现策略模式。以下是我所拥有的:Dependency injection 基于条件的容器解析,dependency-injection,inversion-of-control,castle-windsor,Dependency Injection,Inversion Of Control,Castle Windsor,我试图在使用Windsor容器时实现策略模式。以下是我所拥有的: public class OrderProcessor { ... public OrderProcessor(ITaxStrategy strategy) {} public void Process(Order order) { order.Tax = strategy.CalcTax(order); } } 问题是,我如何配置我的容器(欢迎使用其他容器示例),使其基本上具有选
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(地址)作为注入依赖项的标准?这里有一些选项,请选择您最喜欢的选项。我通常用第一个,它是最简单的
[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; }
}
}
[TestFixture]
公共类税收策略测试{
[测试]
工厂()的公共空间{
var container=新的WindsorContainer();
container.AddComponent();
container.AddComponent();
container.AddComponent();
container.AddComponent();
var order=新订单{Country=“US”};
container.Resolve().Process(订单);
主张平等(10,订单税);
}
[测试]
public void InjectWithFactoryFromDictionary(){
var container=新的WindsorContainer();
container.AddFacility();
container.AddComponent();
container.AddComponent();
container.AddComponent();
container.Register(Component.For())
.UsingFactoryMethod(内核=>new TaxStrategyFactory2(新字典{
{“US”,kernel.Resolve()},
{“CA”,kernel.Resolve()},
})));
var order=新订单{Country=“US”};
container.Resolve().Process(订单);
主张平等(10,订单税);
}
[测试]
public void InjectWithProxy(){
var container=新的WindsorContainer();
container.AddComponent();
container.AddComponent();
container.AddComponent();
container.AddComponent();
container.Register(Component.For())
.短暂的
.Interceptors(InterceptorReference.ForType()).First);
var order=新订单{Country=“CA”};
container.Resolve().Process(订单);
主张平等(5,订单税);
}
公共类OrderProcessorInterceptor:IIInterceptor{
私有只读ITaxStrategyFactory strategyFactory;
公共订单处理程序接口(ITaxStrategyFactory strategyFactory){
this.strategyFactory=strategyFactory;
}
公共无效拦截(IInvocation调用){
if(invocation.MethodInvocationTarget.Name==“进程”){
var processor=(OrderProcessor2)invocation.InvocationTarget;
var order=(order)invocation.Arguments[0];
processor.Strategy=strategyFactory.Create(订单);
}
invocation.procedure();
}
}
公共接口处理器{
作废流程(订单);
}
公共类OrderProcessor2:IOrderProcessor{
公共ITaxStrategy策略{get;set;}
公共虚拟作废流程(订单){
order.Tax=Strategy.CalcTax(order);
}
}
公共类OrderProcessor:IOrderProcessor{
私有只读ITaxStrategyFactory strategyFactory;
公共订单处理器(ITaxStrategyFactory strategyFactory){
this.strategyFactory=strategyFactory;
}
公共作废流程(订单){
var strategy=strategyFactory.Create(订单);
order.Tax=strategy.CalcTax(order);
}
}
公共接口ITaxStrategyFactory{
ITaxStrategy创建(订单o);
}
公共类税收战略工厂:ITaxStrategyFactory{
私有只读IKernel内核;
公共税收战略工厂(IKernel内核){
this.kernel=内核;
}
公共ITaxStrategy创建(订单o){
如果(海外国家=“美国”)
返回kernel.Resolve();
返回kernel.Resolve();
}
}
公共类税收战略工厂2:ITaxStrategyFactory{
私有只读词典策略;
公共税收策略工厂2(词典策略){
这就是战略=战略;
}
公共ITaxStrategy创建(订单o){
返回策略[o.Country];
}
}
公共接口ITAX策略{
十进制CalcTax(订单);
}
公共类USTaxStrategy:ITaxStrategy{
公共十进制计算器(订单){
返回10;
}
}
公共类CanadatXstrategy:ITaxStrategy{
公共十进制计算器(订单){
返回5;
}
}
公共阶级秩序{
公共字符串国家{get;set;}
公共十进制税{get;set;}
}
}
简短回答:编写一个TaxStrategyFactoryHmm-在构建过程中,您将如何向工厂提供参数?非常简单,谢谢Mauricio。我希望温莎有某种标准设施可以(呃)促进选择,并且我可以在没有工厂中间商的情况下依赖ITaxStrategy。这是不可能的,因为容器必须知道特定的订单实例,因此需要代理解决方案。另一种选择是将订单转移到某种上下文中,但这会使事情变得更加复杂。对于那些未来关注的人,我将发布一篇文章并提供一个VS 2K8解决方案示例。