Monday, January 3, 2011

Unity Study Notes (2)

In this article, we are going to the constructor injection , property(setter) injection and Method Injection.

I.Constructor Injection

By the unity documents:
"As an example of constructor injection, if a class that you instantiate using the Resolve method of the Unity container has a constructor that defines one or more dependencies on other classes, the Unity container automatically creates the dependent object instance specified in the parameters of the constructor."

We write sample code as following:

class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();

FirstService serviceInstance1 = container.Resolve< FirstService>();
}
}
public class FirstService
{
public FirstService(SecondService servicea, ThirdService serviceb)
{
servicea.Print("Happy 2011");
serviceb.Write("2011");
}

}

public class SecondService
{
public void Print(string msg)
{
Console.WriteLine("Hello SecondService," + msg);
}
}
public class ThirdService
{
public void Write(string msg)
{
Console.WriteLine("Hello ThirdService,"+msg);
}
}

The same thing, as in Unity Study Notes(1), we can register types for mapping. We write the following code:

class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType< IWriteService, FirstService>()
.RegisterType< PrintBaseClass, SecondService>();
MyService myService = container.Resolve();

}
}

public class MyService
{
public MyService(IWriteService service1, PrintBaseClass service2)
{
service1.Write("Hello 2011");
service2.Print("2011");
}
}

public interface IWriteService
{
void Write(string msg);
}

public class FirstService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("First Service: " +msg);
}
}
public abstract class PrintBaseClass
{
public abstract void Print(string msg);
}

public class SecondService : PrintBaseClass
{
public override void Print(string msg)
{
Console.WriteLine("Second Service: "+msg);
}
}

When a target class contains more than one constructor with the same number of parameters, we should apply InjectionConstructor attribute to the contstructor so that the Unity container knows which constructor the container will use.

We write the sample code below:



class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();

MyService myService = container.Resolve< MyService>();

}
}

public class MyService
{
public MyService(WriteService service)
{
service.Write("Hello 2011");
}

[InjectionConstructor]
public MyService(PrintService service)
{
service.Print("2011");
}
}


public class WriteService
{
public void Write(string msg)
{
Console.WriteLine("We Write: " +msg);
}
}

public class PrintService
{
public void Print(string msg)
{
Console.WriteLine("We Print: "+msg);
}
}

The executing results are like the picture below, we can see the second constructor is called.



II. Property(Setter) Injection

By the unity documents:
"Unity does not automatically set properties as part of creating an instance; you must explicitly configure the container to do so. One way to do this is to apply the Dependency attribute to the property declaration."

We write the sample code below:

class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();

FirstService myService = container.Resolve< FirstService>();

myService.DependentService.Write("2011");

}
}

public class FirstService
{
private SecondService dependentService;

[Dependency]
public SecondService DependentService
{
get { return dependentService; }
set { dependentService = value; }
}

}


public class SecondService
{
public void Write(string msg)
{
Console.WriteLine("We Write: " +msg);
}
}

Notice that if we don't have [Dependency] attribute, there will come out of exception:System.NullReferenceException.

The same thing, we can do register types for mapping:

class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType< IWriteService, FirstService>()
.RegisterType< PrintBaseClass, SecondService>();

MyService myService = container.Resolve();
myService.InterfaceObj.Write("Hello 2011");
myService.BaseObj.Print("2011");

}
}

public class MyService
{
private IWriteService interfaceObj;
private PrintBaseClass baseObj;

[Dependency]
public IWriteService InterfaceObj
{
get { return interfaceObj; }
set { interfaceObj = value; }
}

[Dependency]
public PrintBaseClass BaseObj
{
get { return baseObj; }
set { baseObj = value; }
}

}

public interface IWriteService
{
void Write(string msg);
}

public class FirstService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("First Service: " + msg);
}
}
public abstract class PrintBaseClass
{
public abstract void Print(string msg);
}
public class SecondService : PrintBaseClass
{
public override void Print(string msg)
{
Console.WriteLine("Second Service: "+msg);
}
}

III. Method Injection


The samething, we can do method call injection. You must apply the InjectionMethod attribute in the target class to initiate method call injection.

We write the code below:


using System;
using Microsoft.Practices.Unity;

namespace MethodCallInjectionExample
{
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
FirstService service=container.Resolve< FirstService>();
}
}
public class FirstService
{
[InjectionMethod]
public void MyMethod(SecondService serviceb, ThirdService servicec)
{
serviceb.Print("Hello 2011");
servicec.Write("2011");
}
}

public class SecondService
{
public void Print(string msg)
{
Console.WriteLine("Hello SecondService," + msg);
}
}

public class ThirdService
{
public void Write(string msg)
{
Console.WriteLine("Hello ThirdService," + msg);
}
}
}

We can also register the mappings, for example.
public class FirstService
{
[InjectionMethod]
public void MyMethod(IWriteSerivce interfaceObj1, IPrintService interfaceObj2)
{
.....
}
}

public interface IWriteService
{
void Write(sting msg);
}

public class WriteService:IWriteService
{
public void Write(string msg)
{
....;
}
}

And we use RegisterType do the mappings:

IUnityContainer container=new UnityContainer()
.RegisterType()
.Register();

FirstService service=container.Resolve() to resolve and get the instance.

I write the sample code in this link:
https://docs.google.com/uc?id=0BwzR-spEXHBFYTM4Zjc5ZDItMjM5YS00YWUwLTgyMzItNzkzYjMyZDdkZGM3&export=download&hl=en

No comments: