Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

Dependency Injection in .NET

4.29/5 (6 votes)
25 Feb 2010CPOL2 min read 1  
I'm really on an architecture kick at this point. Honestly, it's probably about time. I find few senior-style job postings that do not ask for some knowledge of Spring.NET or Castle Windsor. Now that I've done a little reading up on the subject, I see that this is for good reason.

I'm really on an architecture kick at this point. Honestly, it's probably about time. I find few senior-style job postings that do not ask for some knowledge of Spring.NET or Castle Windsor. Now that I've done a little reading up on the subject, I see that this is for good reason.

Introduction: What is Dependency Injection?

This stuff is tricky--I'm not going to lie. First of all, I would recommend reading up on the basics. Until you start to really see the power behind defining interfaces and working with abstractions, dependency injection will be unnecessary for you.

Dependency Injection strives to decouple classes from dependencies. For instance:

C#
public interface IComplaintHearer
{
void RegisterComplaint(string message);
}
public class Manager : IComplaintHearer
{
public Manager() { }
public void RegisterComplaint(string message)
{
//do something with message
}
}
public class Employee
{
//completely dependent upon this exact class
private Manager _itsManager;
public Employee() { }
public void Complain(string complaint)
{
_itsManager.RegisterComplaint(complaint);
}
}

What's the issue? What if we want the employee to report to someone other than its immediate boss? Or, what if we want the employee to complain to a co-worker? We would have to completely change the class. Right now this code completely violates the open closed principle (among others) we discussed when reviewing the S.O.L.I.D. principles. So let's use the dependency inversion principle and make this class dependent upon an abstraction:

C#
public interface IComplaintHearer
{
void RegisterComplaint(string message);
}
public class Manager : IComplaintHearer
{
public Manager() { }
public void RegisterComplaint(string message)
{
//do something with message
}
}
public class Employee:IComplaintHearer
{
//completely dependent upon this exact class
private IComplaintHearer _complaintHearer;
public Employee(IComplaintHearer hearer)
{
_complaintHearer=hearer;
}
public void RegisterComplaint(string message)
{
//do something with the message
}
public void Complain(string complaint)
{
_complaintHearer.RegisterComplaint(complaint);
}
}

And we would need to run this code like so:

C#
//we could pass a manager, or another employee if we wanted to
Employee myEmp = new Employee(new Manager());

Injecting the Class, Instead of Providing It

Imagine a scenario where we had tons of classes that implemented the IComplaintHearer interface. We'd have to recompile the code everytime we want to change who the employee complains to. This is where a dependency injection steps in and allows you to:

  1. Specify a class's dependency at run-time
  2. Dynamically use classes in another assembly
  3. Make changes without recompilation

Let's take a look at an example:

C#
public interface IComplaintHearer
{
void RegisterComplaint(string message);
}
public class Manager : IComplaintHearer
{
public Manager() { }
public void RegisterComplaint(string message)
{
//do something with message
}
}
public class Employee:IComplaintHearer
{
//completely dependent upon this exact class
private IComplaintHearer _complaintHearer;

//use the IComplaintHearer subclass that the Dependency Injection Framework 
//(StructureMap in this case) tells us to
// this depends upon the xml that defines what to use (below)
public Employee(): this ( ObjectFactory.GetInstance<icomplainthearer>()){}
public Employee(IComplaintHearer hearer)
{
_complaintHearer=hearer;
}
public void RegisterComplaint(string message)
{
//do something with the message
}
public void Complain(string complaint)
{
_complaintHearer.RegisterComplaint(complaint);
}
}
XML
<structuremap>
<defaultinstance pluggedtype="Example.Manager, Example" 
	plugintype="Example.IComplaintHearer, Example">
</defaultinstance></structuremap>

What just happened? By using the StructureMap Framework for .NET, we just specified the IComplaintHearer that our employee class will default to--the manager. In the XML above, we mapped the expected type/assembly to the default type/assembly. Further, we could set up defaults for all of our classes that we could change later without ever having to change any code. In some ways, I feel like this is moving a problem from one environment to another, but in other ways, I think it is a great architectural tool.

What do you think?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)