Inversion of Control in 5 minutes

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

Imagine You have classes that have dependencies on services or components whose concrete type is specified at design time. To replace or update the dependencies, you would have to change your classes' source code, The concrete implementation of the dependencies must be (in this case) available at compile time. More over such classes are difficult to test in isolation, because they have a direct reference to their dependencies. This means that these dependencies cannot be replaced with mock objects.

Such solution is unfortunately common one. In ideal case You should to decouple your classes from their dependencies. The methodology which helps you solve this problem is called "Inversion of Control".

There are two types (sub-patterns) of Inversion of Control: Dependency Injection and Service Locator.

Dependency Injection

Do not instantiate the dependencies explicitly in the host of your class. IUse 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 (this can alos be done declaratively for example in MEF). Next Figure illustrates this.

Cc707845.360cdd41-4418-4fff-9dee-fc6140458c1d(en-us,MSDN.10).png

In general there are two main forms of dependency injection:

· Constructor injection (Builder creates a class and you inject dependencies in constructor)

· Setter injection (Builder creates a class and you set properties.)

Following example shows constructor injection.

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

}

[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);

}

Service Locator

In this case create a service locator that contains references to the services and that encapsulates the logic to locate them. In your classes, use the service locator to obtain service instances. Next figure illustrates this.

Cc707905.f66cafe4-309e-4f6a-a1e0-8bd75b622b28(en-us,MSDN.10).png

public void Initialize()
{

     RegisterViewsAndServices();
     INewsController controller = _container.Resolve<INewsController>();

     controller.Run();

}

[TestMethod]
public void InitCallsRunOnNewsController()
{

     MockUnityResolver container = new MockUnityResolver();

    var controller = new MockNewsController();

    container.Bag.Add(typeof(INewsController), controller);

    var newsModule = new NewsModule(container);

    newsModule.Initialize();

    Assert.IsTrue(controller.RunCalled);

}

 

For more information: http://msdn.microsoft.com/en-us/library/cc707841.aspx


Posted Feb 04 2009, 12:10 AM by Damir Dobric
developers.de is a .Net Community Blog powered by daenet GmbH.