After working with Ninject and Windsor for a while I finally faced Microsoft Unity dependency injection container. And here is the way to build up an infrastructure for Unity container to use it for example in Unit tests.
Lets take a look at the solution structure:
Service project contains services.
Common project apart from common interfaces contains service locator implementation.
Dependency project contains Unity configuration and registration classes.
Test project contains unit tests for service layer.
For this particular case there will be only one service in Service project:
01 | public interface IFooService |
06 | public class FooService: IFooService |
In order to be able to swap between different DI containers and just for decoupling we define two interfaces in Common project
02 | public interface IServiceLocator |
08 | public interface IContainerRegistrationModule<T> |
10 | void Register(T container); |
IContainerRegistrationModule will come in handy later and now we can define common service locator for any type of DI container:
01 | public abstract class DependencyInjectionServiceLocator<TContainer> : IServiceLocator |
04 | protected TContainer Container { get ; private set ; } |
06 | protected DependencyInjectionServiceLocator(TContainer container) |
08 | Container = container; |
11 | public virtual T Get<T>() |
13 | return Get<T>(Container); |
17 | protected abstract T Get<T>(TContainer container); |
And specific service locator for Unity container:
02 | public class CustomUnityServiceLocator : DependencyInjectionServiceLocator<IUnityContainer> |
04 | public CustomUnityServiceLocator(IUnityContainer container) |
09 | protected override T Get<T>(IUnityContainer container) |
11 | return this .Container.Resolve<T>(); |
Common project is done, moving on to Dependency project. Here we need to define two classes for later usage. First one is registration module where all dependencies will be registered.
01 | public class UnityRegistrationModule : IContainerRegistrationModule<IUnityContainer> |
04 | public void Register(IUnityContainer container) |
07 | container.RegisterType<IServiceLocator, CustomUnityServiceLocator>(); |
10 | container.RegisterType<IFooService, FooService>(); |
And the specific configuration module for Unity:
01 | public class UnityConfig |
03 | private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() => |
05 | var container = new UnityContainer(); |
06 | RegisterTypes(container); |
10 | public static IUnityContainer GetUnityContainer() |
12 | return Container.Value; |
15 | public static void RegisterTypes(IUnityContainer container) |
17 | var registrationModuleAssemblyName = System.Configuration.ConfigurationManager.AppSettings[ "UnityRegistrationModule" ]; |
19 | var type = Type.GetType(registrationModuleAssemblyName); |
21 | var module = (IContainerRegistrationModule<IUnityContainer>)Activator.CreateInstance(type); |
23 | module.Register(container); |
Now you can initialize the container like this:
1 | var unityContainer = UnityConfig.GetUnityContainer() |
Upon calling GetUnityContainer() method new instance of UnityContainer will be initialized, our UnityRegistrationModule will be created and it will register the dependencies.
Notice that UnityRegistrationModule is created via Activator and the assembly and type name added into the App.config configuration file in Test poject:
1 | <? xml version = "1.0" encoding = "utf-8" ?> |
5 | < add key = "UnityRegistrationModule" value = "Dependency.UnityRegistrationModule, Dependency, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> |
Finally lets move on to the Test project. First of all lets define the base test class:
04 | private static IUnityContainer _unityContainer = null ; |
05 | private static IServiceLocator _serviceLocator = null ; |
07 | private static IUnityContainer UnityContainer |
09 | get { return _unityContainer ?? (_unityContainer = UnityConfig.GetUnityContainer()); } |
12 | private static IServiceLocator ServiceLocator |
14 | get { return _serviceLocator ?? (_serviceLocator = UnityContainer.Resolve<IServiceLocator>()); } |
17 | protected TService GetService<TService>() |
19 | return ServiceLocator.Get<TService>(); |
Here we initialize unity container, resolve service locator and define GetService method.
And finally lets create some unit tests:
02 | public class UnitTest1 : TestBase |
05 | public void TestMethod1() |
07 | var service = this .GetService<IFooService>(); |
08 | var result = service.Bar(); |
09 | Assert.IsTrue(result.Length > 0); |
And here it is - FooService successfully resolved using Unity container and our custom service locator.
Download source code
here
from : http://gentlelogic.blogspot.tw/2014/12/c-using-microsoft-unity-dependency.html
沒有留言:
張貼留言