代码之家  ›  专栏  ›  技术社区  ›  tucaz

解决自动和手动依赖关系

  •  5
  • tucaz  · 技术社区  · 14 年前

    我在分类管理类中自动解析和手动依赖的方法时遇到了一点麻烦。

    这两个类都依赖于第三个类,我称之为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);    
    }
    
    5 回复  |  直到 14 年前
        1
  •  7
  •   Community Michael Schmitz    7 年前

    the solution is an Abstract Factory .

    这样的方法应该有用:

    public interface IExchangeRateFactory
    {
        ExchangeRate GetExchangeRate(object runTimeValue);
    }
    

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

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

        2
  •  1
  •   Community Michael Schmitz    7 年前

    你可能会发现 factory delegates providers 是有用的。这两个都是马克(+1d)的答案。

        3
  •  1
  •   tucaz    14 年前

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

    在调用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);    
    }
    

    谢谢你们的帮助!真的很感激!

        4
  •  0
  •   Steven Sudit    14 年前

    将初始化移出构造函数。

        5
  •  0
  •   WW.    14 年前

    根据代码更新:

    //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);    
    }
    

    注意这个方法如何只需要runtimeValue,以便它可以将它传递给其他对象?这是因为对象构造和运行时职责是混合的。我认为您应该在这个方法的构造函数中要求一个iordercollector。

    所以这个方法变成了:

    //WCF Service
    public decimal GetTotalForOrder(Order newOrder, IOrderCalculator calculator)
    {   
        return calculator.CalculateOrderTotal(newOrder);    
    }
    

    现在,当您构造IOrderCalculator时,应该将runtimeValue传递给它的构造函数。当我们不知道runtimeValue是什么或者它来自何处时,就有点难以回答了。