According to Wikipedia Dependency injection (DI) in Computer programming refers to the process of supplying an external dependency to a software component. There are many ways of injecting dependecies into the components. Here is one of the blog post that talks about creating a simple dependency injection framework. In this article we are going to inject dependencies using Castle Windsor Dependency Injection Framework.

Introduction:

According to Wikipedia Dependency injection (DI) in Computer programming refers to the process of supplying an external dependency to a software component. There are many ways of injecting dependecies into the components. Here is one of the blog post that talks about creating a simple dependency injection framework. In this article we are going to inject dependencies using Castle Windsor Dependency Injection Framework.

Application Structure:

We will be creating a very simple windows application using the MVP pattern (Modal View Presenter). There are two projects in this application. One is the Windows Forms application project and the other is the Class Library project which will be used as a Business Objects Layer.

Here is the class diagram of the BusinessObjects project:




The main part of the code is the AddCustomerPresenter since it is dependent on the IAddCustomerView and ICustomerRepository objects.


public class AddCustomerPresenter
    {
        private IAddCustomerView _view;
        private ICustomerRepository _repository;

        public AddCustomerPresenter(IAddCustomerView view, ICustomerRepository repository)
        {
            _view = view;
            _repository = repository;
        }
}



The AddCustomerForm which is a Windows Form is used as a concrete view for the application.


public partial class AddCustomerForm : Form, IAddCustomerView
    {
        private AddCustomerPresenter _presenter;

        public AddCustomerForm()
        {
            InitializeComponent();
        }

              
        public string UserName
        {
            get { throw new NotImplementedException(); }
        }

        public string Message
        {
            set { throw new NotImplementedException(); }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            _presenter = new AddCustomerPresenter(this, new GoodCustomerRepository());
        }
 
Our main interest is in the following line:

presenter = new AddCustomerPresenter(this, new GoodCustomerRepository());

Although this is just a single line but we can see that the AddCustomerPresenter is dependent on the creation of IAddCustomerView and the ICustomerRepository. Currently, the initialization of AddCustomerPresenter is not complicated but this can change over time.

Let’s say that we add a Service in the future then the initialization for the presenter would look something like this:

_presenter = new AddCustomerPresenter(this, new CustomerService(new GoodCustomerRepository()));

As, you can see above the dependency chain is increasing and it is getting harder for the presenter to get initialize since it is dependent on so many other objects. Let’s introduce Castle Windsor to take care of the dependencies.

Downloading Castle Windsor:

Castle Windsor is part of the Castle Project which includes many different components. You can download the Castle Windsor Framework from here. Once, you have download the framework make a reference to the following assemblies:

Castle.Core
Castle.DynamicProxy
Castle.MicroKernel
Castle.Windsor


We will also need to make a small change in the AddCustomerForm windows form. Add a new constructor which takes a presenter as an argument.

public partial class AddCustomerForm : Form, IAddCustomerView
    {
        private AddCustomerPresenter _presenter;

        public AddCustomerForm()
        {
            InitializeComponent();
        }

        public AddCustomerForm(AddCustomerPresenter presenter) : this()
        {
            _presenter = presenter;
        }
}


Now, in the Main static method initialize the dependencies:

     Application.SetCompatibleTextRenderingDefault(false);

            IWindsorContainer container = new WindsorContainer();

            container.AddComponent("AddCustomerPresenter", typeof(AddCustomerPresenter));
            container.AddComponent("IAddCustomerView", typeof(IAddCustomerView),
                typeof(AddCustomerForm));
            container.AddComponent("ICustomerRepository", typeof(ICustomerRepository), typeof(CustomerRepository));
            container.AddComponent("AddCustomerForm", typeof(AddCustomerForm));

            var addCustomerForm = (AddCustomerForm)container[typeof(AddCustomerForm)];

            Application.Run(addCustomerForm);

            container.Release(addCustomerForm);

The WindsorContainer.AddComponent method is used to add dependencies. You will need to register everything that will be used to initialize dependent objects. You will also notice that we are registering the concrete types. The following code registers the ICustomerRepository and uses the concrete type CustomerRepository.

            container.AddComponent("ICustomerRepository", typeof(ICustomerRepository), typeof(CustomerRepository));

When you run the application you will not that your presenter is automatically initialized. You don’t need to supply the View or the Repository because you have already registered it using Castle Windsor.

It is a good idea to move the dependencies to a configuration file. Here are all the dependencies embedded inside the App.config file.

<castle>

    <components>

      <component
           id="AddCustomerPresenter"
           type="LearningStuffSolution.BusinessObjects.Presenters.AddCustomerPresenter, LearningStuffSolution.BusinessObjects">

        <parameters>
          <Url>www.screencastaday.com</Url>
        </parameters>
       
          
      </component>

     
       <component
          id="IAddCustomerView"
          service="LearningStuffSolution.BusinessObjects.Views.IAddCustomerView, LearningStuffSolution.BusinessObjects"
          type="LearningStuffSolution.Windows.UI.AddCustomerForm, LearningStuffSolution.Windows.UI" />


      <component
       id="IBadCustomerRepository"
       service="LearningStuffSolution.BusinessObjects.Repositories.ICustomerRepository, LearningStuffSolution.BusinessObjects"
       type="LearningStuffSolution.BusinessObjects.Repositories.BadCustomerRepository, LearningStuffSolution.BusinessObjects" >


        <component
          id="IGoodCustomerRepository"
          service="LearningStuffSolution.BusinessObjects.Repositories.ICustomerRepository, LearningStuffSolution.BusinessObjects"
          type="LearningStuffSolution.BusinessObjects.Repositories.GoodCustomerRepository, LearningStuffSolution.BusinessObjects" />

                
      </component>

      <component
       id="AddCustomerForm"
       type="LearningStuffSolution.Windows.UI.AddCustomerForm, LearningStuffSolution.Windows.UI">

     

      </component>


    </components>

  </castle>


And here is the code that will read the dependencies from the configuration file and initializes them.

Application.EnableVisualStyles();

            IWindsorContainer container =
            new WindsorContainer(
                new XmlInterpreter(new ConfigResource("castle")));

            // Request the component to use it
            AddCustomerForm form = (AddCustomerForm)container[typeof(AddCustomerForm)];

            // Use the component
            Application.Run(form);

            // Release it
            container.Release(form);

You might be thinking that what will happen when you introduce a new parameter to any object. You can use the parameters tag inside the configuration file which will map to the actual parameter. Let’s introduce a Url property to our AddCustomerPresenter.

public class AddCustomerPresenter
    {
        private IAddCustomerView _view;
        private ICustomerRepository _repository;

        public AddCustomerPresenter(IAddCustomerView view, ICustomerRepository repository)
        {
            _view = view;
            _repository = repository;
        }

        public string Url { get; set; }
}


We can initialize the Url property by wiring it up inside the configuration file:

<component
           id="AddCustomerPresenter"
           type="LearningStuffSolution.BusinessObjects.Presenters
.AddCustomerPresenter, LearningStuffSolution.BusinessObjects">

        <parameters>
          <Url>www.screencastaday.com</Url>
        </parameters>
       
          
      </component>


That’s about it!

[Download Sample]

We also recommend that you check out the following screen casts.

Introduction to Dependency Injection Using Castle Windsor

Castle Windsor Moving Dependencies into Application Config