Forms of Dependency Injection
Untiy supports three main styles of dependency injection: Constructor Injection, Property(Setter) Injection and Method Call Injection. The following examples demonstrate how dependencies can be injected using these injections.
Constructor Injection
We have already seen dependency injection through the constructor in the above code, but there is one important note about this: If your class has multiple constructors, your must annotate the constructor you want UnityContainer to use by adding the [InjectionConstructor] attribute on it.
Property(Setter) Injection
Add these 3 classes to your project:
namespace DIConsoleDemo
{
public interface ICustomer
{
string Name
{
get;
}
}
}
namespace DIConsoleDemo
{
public class CustomerA : ICustomer
{
public string Name
{
get
{
return "Custoemr A";
}
}
}
}
namespace DIConsoleDemo
{
public class CustomerB : ICustomer
{
public string Name
{
get
{
return "Custoemr B";
}
}
}
}
Modify the configuartion file as the following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<typeAliases>
<typeAlias alias="IInvoice" type="DIConsoleDemo.IInvoice, DIConsoleDemo" />
<typeAlias alias="InvoiceA" type="DIConsoleDemo.InvoiceA, DIConsoleDemo" />
<typeAlias alias="InvoiceB" type="DIConsoleDemo.InvoiceB, DIConsoleDemo" />
<typeAlias alias="ICustomer" type="DIConsoleDemo.ICustomer, DIConsoleDemo" />
<typeAlias alias="CustomerA" type="DIConsoleDemo.CustomerA, DIConsoleDemo" />
<typeAlias alias="CustomerB" type="DIConsoleDemo.CustomerB, DIConsoleDemo" />
</typeAliases>
<containers>
<container>
<types>
<type type ="IInvoice" mapTo="InvoiceA" />
<type type ="ICustomer" mapTo="CustomerA" />
</types>
</container>
</containers>
</unity>
</configuration>
Modify the InvoiceManager by adding a new Propertyof the Customer and logic for IssueInvoice method:
using Microsoft.Practices.Unity;
namespace DIConsoleDemo
{
class InvoiceManager
{
private IInvoice _invoice;
private ICustomer _customer;
public InvoiceManager(IInvoice invoice)
{
_invoice = invoice;
}
[Dependency]
public ICustomer Customer
{
get
{
return this._customer;
}
set
{
this._customer = value;
}
}
public void IssueInvoice()
{
Console.WriteLine(this._customer.Name);
Console.WriteLine(this._invoice.Title);
}
}
}
Notice the use of the [Dependency] attribute. This will indicate to the UnityContainer that a dependency injection is required here.
Build and run the project, you will see the result:
Customer A
Invoice A
The program did resolve ICustomer and injected a CustomerA instance into the InvoiceManager.Customer property.
Method Call Injection
You can do pretty much the same thing using a method call instead of a property.
Replace the Customer the property by a SetCustomer() method:
using Microsoft.Practices.Unity;
namespace DIConsoleDemo
{
class InvoiceManager
{
private IInvoice _invoice;
private ICustomer _customer;
public InvoiceManager(IInvoice invoice)
{
_invoice = invoice;
}
[InjectionMethod]
public void SetCustomer(ICustomer customer)
{
this._customer = customer;
}
public void IssueInvoice()
{
Console.WriteLine(this._customer.Name);
Console.WriteLine(this._invoice.Title);
}
}
}
In the case of a method, use the [InjectionMethod] attribute to indicate to UnityContainer that a dependency injection is required.
Build and run the project. The program did resolve ICustomer and injected a CustomerA instance by calling the InvoiceManager.SetCustomer method.