This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
You have classes that have dependencies on services or components whose concrete type is specified at design time. In this example, ClassA has dependencies on ServiceA and ServiceB. Figure 1 illustrates this.
Figure 1 ClassA has dependencies on ServiceA and ServiceB
This situation has the following constraints:
Any of the following conditions justifies using the solution described in this pattern:
Do not instantiate the dependencies explicitly in your class. Instead, declaratively express dependencies in your class definition. Use a Builder object to obtain valid instances of your object's dependencies and pass them to your object during the object's creation and/or initialization. Figure 2 illustrates this.
Figure 2 Conceptual view of the Dependency Injection pattern
Note: |
Typically, you express dependencies on interfaces instead of concrete classes. This enables easy replacement of the dependency concrete implementation without modifying your classes' source code. |
The following are the two main forms of dependency injection:
In constructor injection, you use parameters of the object's constructor method to express dependencies and to have the builder inject it with its dependencies. In setter injection, the dependencies are expressed through setter properties that the builder uses to pass the dependencies to it during object initialization.
The Dependency Injection pattern can be implemented in several ways. The Unity Application Block (Unity) provides a container that can be used for dependency injection. For more information about the Unity Application Block, see Unity Application Block.
The NewsReaderPresenter class of the Stock Trader Reference Implementation (located at StockTraderRI.Modules.News\Article\NewsReaderPresenter.cs) uses constructor dependency injection to obtain a valid instance of a view that implements the INewsReaderView interface. The class definition is shown in the following code.
C#
public class NewsReaderPresenter : INewsReaderPresenter{ private INewsReaderView readerView; public NewsReaderPresenter(INewsReaderView view) { this.readerView = view; } public void SetNewsArticle(NewsArticle article) { readerView.Model = article; } public void Show() { readerView.ShowView(); }}
Because the NewsReaderPresenter class uses dependency injection to obtain its dependencies, its dependencies can be replaced with mock implementations when testing. The following test methods, taken from the fixture file StockTraderRI.Modules.News.Tests\NewsView\NewsReaderPresenterFixture.cs, show how the NewsReaderPresenter class can be tested in isolation using mock implementations to replace the classes' dependencies and verify behavior.
C#
[TestMethod]public void ShowInformsViewToShow(){ var view = new MockNewsReaderView(); var presenter = new NewsReaderPresenter(view); presenter.Show(); Assert.IsTrue(view.ShowViewWasCalled);} [TestMethod]public void SetNewsArticlesSetsViewModel(){ var view = new MockNewsReaderView(); var presenter = new NewsReaderPresenter(view); NewsArticle article = new NewsArticle() { Title = "My Title", Body = "My Body" }; presenter.SetNewsArticle(article); Assert.AreSame(article,view.Model);}
The dependency injection pattern has the following liabilities:
The following patterns are related to the Dependency Injection pattern:
For more information on the Dependency Injection pattern, see the following: