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); }
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.
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.
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”.
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.
You may find injecting factory delegates or providers to be useful. Both are pretty much impls of Mark's (+1d) answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With