Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving automatic and manual dependencies

I´m having a little bit of trouble sorting a way to manage automatic resolved and manual dependencies in my classes.

Let´s say I have two classes to calculate prices: one calculates how much I will charge for shipping and the other how much I will charge for the entire order. The second uses the first in order to sum the shipping price to the entire order price.

Both classes have a dependency to a third class that I will call ExchangeRate which gives me the exchange rate I should use for price calculation.

So far we have this chain of dependency:

OrderCalculator -> ShippingCalculator -> ExchangeRate

I´m using Ninject to resolve these dependencies and this was working until now. Now I have a requirement that the rate returned by ExchangeRate class will vary upon a parameter that will be provided in the Constructor (because the object won´t work without this, so to make the dependency explicit it´s placed on the constructor) coming from a user input. Because of that I can no longer resolve my dependencies automatically.

Whenever I want to the OrderCalculator or any other classes that depends on ExchangeRate I cannot ask the Ninject container to resolve it to me since I need to provide the parameter in the constructor.

What do u suggest in this case?

Thanks!

EDIT: Let's add some code

This chain of objects is consumed by a WCF service and I'm using Ninject as the DI container.

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);    
}
like image 392
tucaz Avatar asked Jul 26 '10 14:07

tucaz


People also ask

What does it mean to resolve dependencies?

Dependency resolution is a process that consists of two phases, which are repeated until the dependency graph is complete: When a new dependency is added to the graph, perform conflict resolution to determine which version should be added to the graph.

What are dependencies in Java?

Dependency injection enables you to turn regular Java classes into managed objects and to inject them into any other managed object. Using dependency injection, your code can declare dependencies on any managed object.

What is Unity dependency injection?

Dependency Injection (DI) Dependency Injection is defined as a design pattern that allows removing hard-coded dependencies from an application. There is one major point to remember: “Inversion of control is principal and Dependency Injection is implementation”.


2 Answers

As always, when you have a partial dependency on a run-time value, the solution is an Abstract Factory.

Something like this should work:

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

Now inject an IExchangeRateFactory into your consumers instead of ExchangeRate and use the GetExchangeRate method to convert the run-time value to an ExchangeRate instance.

Obviously you will also need to provide an implementation of IExchangeRateFactory and configure NInject to map the interface to your implementation.

like image 101
Mark Seemann Avatar answered Sep 23 '22 05:09

Mark Seemann


You may find injecting factory delegates or providers to be useful. Both are pretty much impls of Mark's (+1d) answer.

like image 31
Ruben Bartelink Avatar answered Sep 25 '22 05:09

Ruben Bartelink