C/C++

Dependency Injection

By Mark Seeman, October 01, 2013

By injecting methods, it's possible to insert different actions into a function without changing code  the ultimate in loose coupling.

Example: Converting Currency

In a sample e-commerce application, a BasketController, which manages the user's shopping basked, retrieves the user's preferred currency. I'll show the currency conversion example by converting a Basket to the user's currency. Currency is an abstraction that models a currency.

The Code property returns the currency code for the Currency instance. Currency codes are expected to be international currency codes. For example, the currency code for Danish Kroner is DKK, whereas it's USD for US Dollars.

The GetExchangeRateFor method returns the exchange rate between the Currency instance and some other currency. Notice that this is an abstract method, which means that I'm making no assumptions about how that exchange rate is going to be found by the implementer.

In the next section, I'll examine how Currency instances are used to convert prices, and how this abstraction can be implemented and wired up so that you can convert some prices into such exotic currencies as US Dollars or Euros.

I'll use the Currency abstraction as an information-carrying dependency to perform currency conversions of Baskets, so I'll add a ConvertTo method to the Basket class:

public Basket ConvertTo(Currency currency)

This will loop through all the items in the basket and convert their calculated prices to the provided currency, returning a new Basket instance with the converted items.

Through a series of delegated method calls, the implementation is provided by the Money class:

The Currency is injected into the ConvertTo method via the currency parameter (line 1) and checked by the ubiquitous guard clause that guarantees the currency instance is available to the rest of the method body.

The exchange rate to the current currency (represented by this.CurrencyCode) is retrieved from the supplied currency and used to calculate and return the new Money instance.

With the implementation of the ConvertTo methods, I can implement the Index method on the BasketController:

The BasketController uses an IBasketService instance to retrieve the user's Basket. Once you have the Basket instance, you can convert it to the desired currency by using the ConvertTo method, passing in the currency instance (line 9).

In this case, you're using method injection because the Currency abstraction is information-carrying, but will vary by context (depending on the user's selection).
You could have implemented the Currency type as a concrete class, but that would have constrained your ability to define how exchange rates are retrieved. Now that we've seen how the Currency class is used, it's time to change our viewpoint and examine how it might be implemented.

Implementing Currency

The Currency instance is served by a CurrencyProvider instance that was injected into the BasketController class at class creation by constructor injection. Let's look at this.

The dependencies (saved as read-only fields in lines 1 and 2) are injected into the controller by the call to the constructor (lines 4-5).
To keep the example simple, let's look at how you might implement CurrencyProvider and Currency using a SQL Server database and LINQ to Entities. This assumes that the database has a table with exchange rates that has been populated in advance by some external mechanism. You could also have used a Web service to request exchange rates from an external source.

The CurrencyProvider implementation passes a connection string on to the Currency implementation that uses this information to create an ObjectContext. The heart of the matter is the implementation of the GetExchangeRateFor method:

The first thing to do is get the rates from the database. The table contains rates as defined against a single, common currency (DKK), so you need both rates to be able to perform a proper conversion between two arbitrary currencies. You will index the retrieved currencies by currency code so that you can easily look them up in the final step of the calculation.

This implementation potentially performs a lot of out-of-process communication with the database. The ConvertTo method of Basket eventually calls this method in a tight loop, and hitting the database for each call is likely to be detrimental to performance.

Related Patterns

Method injection is mainly used when we already have an instance of the dependency we want to pass on to collaborators, but where we don't know the concrete types of the collaborators at design time (as is the case with add-ins).

Note that with method injection, we're on the other side of the fence compared with other dependency injection patterns: We don't consume the dependency, we supply it.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!