Table of Contents
- Introduction
- Roadmap
- Existing Design and Problem
- Managed Extensibility Framework (MEF)
- Creating a Dependency Resolver with Unity and MEF
- Setup Business Services
- Setup DataModel
- Setup REST endpoint / WebAPI project
- Running the application
- Advantages of this design
- Conclusion
Introduction
In my last two articles I explained how to create a RESTful service using ASP.Net Web API working with Entity Framework and resolving dependencies using Unity Container. This article explains how to create a loosely-coupled system with Unity Container and Managed Extensibility Framework (MEF) using Inversion of Control. I'll not be explaining much theory but rather focus more on practical implementations. For the readers who are following this series, they can use their existing solution that they have created previously. For my new readers of this article, I have provided the download link for the previous source code and current source code as well.
For theory and understanding of DI and IOC you can use the following links: Unity and Inversion of Control(IOC).
Roadmap
Here is my roadmap for learning RESTful APIs:
I'll intentionally use Visual Studio 2010 and .NET Framework 4.0 because there are a few implementations that are very hard to find in .NET Framework 4.0, but I'll make it easy by showing how to do it.
Existing Design and Problem
We already have an existing design. If you open the solution, you'll get to see the structure as shown below:
We tried to design a loosely-coupled architecture in the following way:
DataModel (responsible for communication with database): Only talks to the service layer.
Services (acting as a business logic layer between the REST endpoint and data access)
communicates between the REST endpoint and DataModel.
REST API, in other words Controllers: Only talks to services via the interfaces exposed.
But when we tried to resolve the dependency of UnitOfWork from Services, we had to reference the DataModel DLL in our WebAPI project. This violated our system as shown in the following image.
In this article we'll try to resolve the dependency (data model) of a dependency (services) from our existing solution. My controller depended on services and my services depended on the data model. Now we'll design an architecture in which components will be independent of each other in terms of object creation and instantiation. To do this we'll use the Managed Extensibility Framework (MEF) along with Unity Container and reflection.
- container.RegisterType<IProductServices, ProductServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());
Managed Extensibility Framework (MEF)You can have a read about Unity from the
MSDN link. The following is a quote from the MSDN:
“The Managed Extensibility Framework or MEF is a library for creating lightweight, extensible applications. It allows application developers to discover and use extensions with no configuration required. It also lets extension developers easily encapsulate code and avoid fragile hard dependencies. MEF not only allows extensions to be reused within applications, but across applications as well.”“MEF is an integral part of the .NET Framework 4 and is available wherever the .NET Framework is used. You can use MEF in your client applications, whether they use Windows Forms, WPF, or any other technology, or in server applications that use ASP.NET.”Creating a Dependency Resolver with Unity and MEFOpen your Visual Studio, I am using Visual Studio 2010, you can use Visual Studio version 2010 or above. Load the solution.
Step 1
Right-click the Solution Explorer and add a new project named Resolver as in the following:
I have intentionally chosen this name and you already know it why.
Step 2
Right-click the Resolver project and click on ManageNugetPackage, in the interface for adding the new package, search for Unity.MVC3 in the online library as in the following:
Install the package into your solution.
Step 3Right-click the resolver project and add a reference for System.ComponentModel.Composition.
You can find the DLL in your GAC. I am using Framework 4.0, so referring to the same version DLL.
This DLL is part of MEF and is already installed with .NET Framework 4.0 in the system GAC. This DLL provides classes that are the very core of MEF.
Step 4 Just add an interface named IComponent to the Resolver project that contains the initialization method named Setup. We'll try to implement this interface in our Resolver class that we'll create in our other projects, like DataModel, Services and WebApI.
- namespace Resolver
- {
-
-
-
- public interface IComponent
- {
- }
- }
Step 5
Before we declare our Setup method, just add one more interface responsible for serving as a contract to register types. I name this interface IRegisterComponent as in the following:
- namespace Resolver
- {
-
-
-
- public interface IRegisterComponent
- {
-
-
-
-
-
-
- void RegisterType<TFrom, TTo>(bool withInterception = false) where TTo : TFrom;
-
-
-
-
-
-
- void RegisterTypeWithControlledLifeTime<TFrom, TTo>(bool withInterception = false) where TTo : TFrom;
- }
- }
In this interface I have declared two methods, one RegisterType and other into RegisterType with Controlled life time of the object, in other words the life time of an object will be hierarchal in manner. This is kind of the same as we do in Unity.
Step 6
Now declare a Setup method on our previously created IComponent interface, that takes an instance of IRegisterComponent as a parameter as in the following:
void SetUp(IRegisterComponent registerComponent);
So our IComponent interface becomes:
- namespace Resolver
- {
-
-
-
- public interface IComponent
- {
- void SetUp(IRegisterComponent registerComponent);
- }
- }
Step 7
Now we'll write a packager, or you can say a wrapper, over MEF and Unity to register types/ components. This is the core MEF implementation. Create a class named ComponentLoader and add the following code to it:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.Practices.Unity;
- using System.ComponentModel.Composition.Hosting;
- using System.ComponentModel.Composition.Primitives;
- using System.Reflection;
-
- namespace Resolver
- {
- public static class ComponentLoader
- {
- public static void LoadContainer(IUnityContainer container, string path, string pattern)
- {
- var dirCat = new DirectoryCatalog(path, pattern);
- var importDef = BuildImportDefinition();
- try
- {
- using (var aggregateCatalog = new AggregateCatalog())
- {
- aggregateCatalog.Catalogs.Add(dirCat);
-
- using (var componsitionContainer = new CompositionContainer(aggregateCatalog))
- {
- IEnumerable<Export> exports = componsitionContainer.GetExports(importDef);
-
- IEnumerable<IComponent> modules =
- exports.Select(export => export.Value as IComponent).Where(m => m != null);
-
- var registerComponent = new RegisterComponent(container);
- foreach (IComponent module in modules)
- {
- module.SetUp(registerComponent);
- }
- }
- }
- }
- catch (ReflectionTypeLoadException typeLoadException)
- {
- var builder = new StringBuilder();
- foreach (Exception loaderException in typeLoadException.LoaderExceptions)
- {
- builder.AppendFormat("{0}\n", loaderException.Message);
- }
-
- throw new TypeLoadException(builder.ToString(), typeLoadException);
- }
- }
-
- private static ImportDefinition BuildImportDefinition()
- {
- return new ImportDefinition(
- def => true, typeof(IComponent).FullName, ImportCardinality.ZeroOrMore, false, false);
- }
- }
-
- internal class RegisterComponent : IRegisterComponent
- {
- private readonly IUnityContainer _container;
-
- public RegisterComponent(IUnityContainer container)
- {
- this._container = container;
-
- }
-
- public void RegisterType<TFrom, TTo>(bool withInterception = false) where TTo : TFrom
- {
- if (withInterception)
- {
-
- }
- else
- {
- this._container.RegisterType<TFrom, TTo>();
- }
- }
-
- public void RegisterTypeWithControlledLifeTime<TFrom, TTo>(bool withInterception = false) where TTo : TFrom
- {
- this._container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager());
- }
- }
- }
Step 8 Now our Resolver wrapper is ready. Build the project and add its reference to the DataModel, BusinessServices and WebApi projects like shown below.
Setup Business ServicesWe have already added a reference of Resolver in the BusinessServices project. We agreed to implement the IComponent interface in each of our projects.
So create a class named DependencyResolver and implement an IComponent interface into it. We use reflection too to import the IComponent type. So add a class and add the following code to that DependencyResolver class:
- using System.ComponentModel.Composition;
- using DataModel;
- using DataModel.UnitOfWork;
- using Resolver;
-
- namespace BusinessServices
- {
- [Export(typeof(IComponent))]
- public class DependencyResolver : IComponent
- {
- public void SetUp(IRegisterComponent registerComponent)
- {
- registerComponent.RegisterType<IProductServices, ProductServices>();
-
- }
- }
- }
Note that we have implemented the SetUp method and in the same method we registered the type for my ProductService.
All of the existing codebase remains the same. We don't need to touch the IProductServices interface or ProductServices class.
Setup DataModel
We have added a Resolver project reference to the DataModel project as well. So we'll try to register the type of UnitOfWork in this project. We proceed in the same fashion, just add a DependencyResolver class and implement its Setup method to register a type of UnitOfWork. To make the code more readable and standard, I made a change. I just added an interface for UnitOfWork and named it IUnitOfWork. Now my UnitOfWork class derives from this, you can do this exercise in earlier versions of projects we discussed in the first two articles.
So my IUnitOfWork contains a declaration of a single public method in UnitOfWork as in the following:
- namespace DataModel.UnitOfWork
- {
- public interface IUnitOfWork
- {
-
-
-
- void Save();
- }
- }
Now register the type for UnitOfWork in the DepenencyResolver class. Our class becomes as shown below:
- using System.ComponentModel.Composition;
- using System.Data.Entity;
- using DataModel.UnitOfWork;
- using Resolver;
-
- namespace DataModel
- {
- [Export(typeof(IComponent))]
- public class DependencyResolver : IComponent
- {
- public void SetUp(IRegisterComponent registerComponent)
- {
- registerComponent.RegisterType<IUnitOfWork,UnitOfWork.UnitOfWork>();
- }
- }
- }
Again, there is no need to touch any existing code of this project.
Setup REST endpoint / WebAPI project90% of the job is done.
We now need to set up the WebAPI project.We'll not add any DependencyResolver class to this project. We'll invert the calling mechanism of layers in the Bootstrapper class that we already have, so when you open your bootstrapper class, you'll get the code, something like:
- using System.Web.Http;
- using System.Web.Mvc;
- using BusinessServices;
- using DataModel.UnitOfWork;
- using Microsoft.Practices.Unity;
- using Unity.Mvc3;
-
- namespace WebApi
- {
- public static class Bootstrapper
- {
- public static void Initialise()
- {
- var container = BuildUnityContainer();
-
- DependencyResolver.SetResolver(new UnityDependencyResolver(container));
-
-
- GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
- }
-
- private static IUnityContainer BuildUnityContainer()
- {
- var container = new UnityContainer();
-
-
-
-
-
- container.RegisterType<IProductServices, ProductServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());
-
- return container;
- }
- }
- }
Now, we need to change the codebase a bit to make our system loosely-coupled. Just remove the reference of DataModel from the WebAPI project.
Let me revise what is the job of "HierarchicalLifetimeManager",
"HierarchicalLifetimeManager" , for this lifetime manager, as for the ContainerControlledLifetimeManager, Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. The distinction is that when there are child containers, each child resolves its own instance of the object and does not share one with the parent. When resolving in the parent, the behavior is like a container controlled lifetime; when resolving the parent and the child you have different instances with each acting as a container-controlled lifetime. If you have multiple children, each will resolve its own instance.
We don't want our DataModel to be exposed to the WebAPI project. That was our intent though, so we cut down the dependency of the DataModel project now.
Add the following code of the Bootstrapper class to the existing Bootstarpper class:
- using System.Web.Http;
-
- using Microsoft.Practices.Unity;
- using Resolver;
- using Unity.Mvc3;
-
- namespace WebApi
- {
- public static class Bootstrapper
- {
- public static void Initialise()
- {
- var container = BuildUnityContainer();
-
- System.Web.Mvc.DependencyResolver.SetResolver(new UnityDependencyResolver(container));
-
-
- GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
- }
-
- private static IUnityContainer BuildUnityContainer()
- {
- var container = new UnityContainer();
-
-
-
-
-
-
-
- RegisterTypes(container);
-
- return container;
- }
-
- public static void RegisterTypes(IUnityContainer container)
- {
-
-
- ComponentLoader.LoadContainer(container, ".\\bin", "WebApi.dll");
- ComponentLoader.LoadContainer(container, ".\\bin", "BusinessServices.dll");
-
- }
- }
- }
It is kind of redefining the Bootstrapper class without touching our existing controller methods. We now don't even need to register the type for ProductServices as well, we already did this in the BusinessServices project.
Note that in the RegisterTypes method we load the components/DLLs using reflection using ComponentLoader.We wrote two lines, first to load the WebAPI.dll and another one to load Business Services.dll.
Had the name of the BusinessServicess.dll been WebAPI.Services.dll then we would have only written one line of code to load both the WebAPI and the BusinessService DLL as shown below.
- ComponentLoader.LoadContainer(container, ".\\bin", "WebApi*.dll");
Yes we can use a Regex.
Running the applicationJust run the application. We get:
We already have our test client added, but for new readers, just go to Manage Nuget Packages by right-clicking the WebAPI project and type WebAPITestClient into the searchbox in online packages as in the following:
You'll get “A simple Test Client for ASP.NET Web API”, just add it. You'll get a help controller in Areas -> HelpPage as shown below.
I have already provided the database scripts and data in my previous article, you can use that.
Append “/help” to the application URL and you'll get the test client as in the following:
You can test each service by clicking on it.
Service for GetAllProduct:
To create a new product:
In the database, we get a new product as in the following:
Update product:
We get in the database:
Delete product:
In the database:
Advantages of this designIn my earlier articles I focussed more on design flaws, but our current design has emerged with a few added advantages.
We got an extensible and loosely-coupled application design that can go far with more new components added in the same way.
Registering types automatically using reflection. Assume we want to register any Interface implementation to our REST endpoint, we just need to load that DLL into our Bootstrapper class, or if the DLLs share a common suffix of the names then we just need to place that DLL in the bin folder and that will automatically be loaded at run time.
Image source: http://a.pragprog.com/magazines/2013-07/images/iStock_000021011143XSmall__1mfk9b__.jpg
Database transactions or any of such module is now not exposed to the service endpoint, this makes our service more secure and maintains the design structure too.
Conclusion
We now know how to use a Unity container to resolve dependency and perform inversion of control using MEF too. In my next article I'll try to explain how to open multiple endpoints to our REST service and create custom URLs in the true REST fashion in my WebAPI. Until then Happy Coding. You can also download the source code from GitHub. Add the required packages, if they are missing in the source code.
Read more:
For more technical articles you can reach out to CodeTeddy
My other series of articles: