解决自动和手动依赖关系

tuc*_*caz 5 c# dependency-injection ninject inversion-of-control

我在排序管理类中自动解析和手动依赖的方法时遇到了一些麻烦.

假设我有两个课程来计算价格:一个计算我将收取多少运费,另一个计算我将为整个订单收取多少费用.第二个使用第一个,以便将运费与整个订单价格相加.

这两个类都依赖于第三类,我将其称为ExchangeRate,它给出了我应该用于计算价格的汇率.

到目前为止,我们有这种依赖链:

OrderCalculator - > ShippingCalculator - > ExchangeRate

我正在使用Ninject来解决这些依赖关系,这一直在使用.现在我要求ExchangeRate类返回的速率将根据将在构造函数中提供的参数而变化(因为对象不能在没有这个的情况下工作,因此要使依赖项显式放置在构造函数上)来自用户输入.因此,我无法再自动解析我的依赖项.

每当我想要OrderCalculator或依赖于ExchangeRate的任何其他类时,我都不能要求Ninject容器解析它,因为我需要在构造函数中提供参数.

在这种情况下你有什么建议?

谢谢!

编辑:我们添加一些代码

这个对象链由WCF服务使用,我使用Ninject作为DI容器.

public class OrderCalculator : IOrderCalculator
{ 
        private IExchangeRate _exchangeRate; 
        public OrderCalculator(IExchangeRate exchangeRate) 
        { 
                _exchangeRate = exchangeRate; 
        } 
        public decimal CalculateOrderTotal(Order newOrder) 
        { 
                var total = 0m; 
                foreach(var item in newOrder.Items) 
                { 
                        total += item.Price * _exchangeRate.GetRate();
                } 
                return total;               
        } 
} 

public class ExchangeRate : IExchangeRate 
{ 
        private RunTimeClass _runtimeValue; 
        public ExchangeRate(RunTimeClass runtimeValue) 
        { 
                _runtimeValue = runtimeValue; 
        } 
        public decimal GetRate() 
        { 
                //returns the rate according to _runtimeValue
                if(_runtimeValue == 1) 
                        return 15.3m; 
                else if(_runtimeValue == 2) 
                        return 9.9m 
                else 
                        return 30m; 
        } 
} 

//WCF Service
public decimal GetTotalForOrder(Order newOrder, RunTimeClass runtimeValue)
{   
    //I would like to pass the runtimeValue when resolving the IOrderCalculator depedency using a dictionary or something
    //Something like this ObjectFactory.Resolve(runtimeValue);
    IOrderCalculator calculator = ObjectFactory.Resolve();    
    return calculator.CalculateOrderTotal(newOrder);    
}

Mar*_*ann 7

与往常一样,当您对运行时值具有部分依赖性时,解决方案是抽象工厂.

这样的事情应该有效:

public interface IExchangeRateFactory
{
    ExchangeRate GetExchangeRate(object runTimeValue);
}
Run Code Online (Sandbox Code Playgroud)

现在将IExchangeRateFactory注入到使用者而不是ExchangeRate中,并使用GetExchangeRate方法将运行时值转换为ExchangeRate实例.

显然,您还需要提供IExchangeRateFactory的实现并配置NInject以将接口映射到您的实现.


tuc*_*caz 1

我最终做了一些完全不同的事情。

在调用 ObjectFactory 为我解决依赖关系之前,我使用 runTimeValue 创建 IExchangeRate 的一个新实例,并告诉 IoC/DI 容器使用它而不是创建一个新实例。这样,整个对象链都被保留,并且不需要工厂。


//WCF Service
public decimal GetTotalForOrder(Order newOrder, RunTimeClass runtimeValue)
{   
    IExchangeRate ex = new ExchangeRate(runtimeValue);
    IOrderCalculator calculator = ObjectFactory.With<IExchangeRate>(ex).GetInstance();
    return calculator.CalculateOrderTotal(newOrder);    
}
Run Code Online (Sandbox Code Playgroud)

但由于 Ninject 没有办法做到这一点(只能重新绑定,这不是我想要的),我将容器更改为 StructureMap。

感谢大家的帮助!真的很感激!