Introduction
How to use the Unity container to add support for dependency injection to a real-world application and how you can use a Unity container to register types, resolve types at runtime, and manage the lifetime of the resolved objects. In addition to seeing how the Unity container made it possible to build the application’s object graph at startup, you also saw how this approach facilitated designing and running unit tests.
Background
I quoted information about Unity from article: http://unity.codeplex.com
The Unity Application Block (Unity) is a lightweight extensible dependency injection container with support for constructor, property, and method call injection.
Unity addresses the issues faced by developers engaged in component-based software engineering. Modern business applications consist of custom business objects and components that perform specific or generic tasks within the application, in addition to components that individually address cross cutting concerns such as logging, authentication, authorization, caching, and exception handling.
The key to successfully building such applications is to achieve a decoupled or very loosely coupled design. Loosely coupled applications are more flexible and easier to maintain. They are also easier to test during development. You can mock up shims (lightweight mock implementations) of objects that have strong concrete dependencies; such as database connections, network connections, ERP connections, and rich user interface components.
Dependency injection is a prime technique for building loosely coupled applications. It provides ways to handle the dependencies between objects. For example, an object that processes customer information may depend on other objects that access the data store, validate the information, and check that the user is authorized to perform updates. Dependency injection techniques can ensure that the customer class correctly instantiates and populates all of these objects, especially where the dependencies may be abstract.
Using Code (EF with CODE FIRST)
0. Preparing
Create an ASP.NET MVC with existing template in Visual Studio 2012 or 2013.
Install package:
1. Create a Table in Database
First, we create a table with name being Articles
in the database as below:
CREATE TABLE [dbo].[Articles]
(
[Id] [uniqueidentifier] NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[Summary] [nvarchar](500) NULL,
[ArticleContent] [nvarchar](max) NULL,
[ViewCount] [int] NULL,
[CreatedDate] [datetime] NULL,
[CreatedByUsername] [varchar](50) NULL,
[Tags] [nvarchar](500) NULL,
CONSTRAINT [PK_Articles] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
)
2. Create a Class Article in Folder Models of an ASP.NET MVC Project
Second, we create a class with name as Article
(in folder Models of an ASP.NET MVC project) corresponding table Articles
in database as below:
using System;
namespace UnityTutorials.Models
{
public class Article
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Summary { get; set; }
public string ArticleContent { get; set; }
public int ViewCount { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public string Tags { get; set; }
}
}
3. Create a Class ArticleMapping in Folder Models of an ASP.NET MVC Project
Third, we create a class with name ArticleMapping
(in folder Models of an ASP.NET MVC project) as below:
using System.Data.Entity.ModelConfiguration;
namespace UnityTutorials.Models
{
public class ArticleMapping : EntityTypeConfiguration<Article>
{
public ArticleMapping()
{
this.HasKey(x => x.Id);
this.ToTable("Articles"); }
}
}
4. Create an Interface IWebDbContext and a Class WebDbContext Implement IWebDbContext Interface in Folder Models of an ASP.NET MVC Project
using System;
using System.Data.Entity;
namespace UnityTutorials.Models
{
public interface IWebDbContext : IDisposable
{
}
public class WebDbContext : DbContext, IWebDbContext
{
public DbSet<Article> Articles { get; set; }
public WebDbContext()
{
Configuration.LazyLoadingEnabled = true;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ArticleMapping());
base.OnModelCreating(modelBuilder);
}
public new void Dispose()
{
}
}
}
5. Create a Class ArticleRepository in Folder Models of an ASP.NET MVC Project
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace UnityTutorials.Models
{
public interface IArticleRepository
{
IEnumerable<Article> GetAll();
Article Add(Article item);
void Update(Article item);
void Delete(Article item);
Article Get(Guid id);
}
public class ArticleRepository : IArticleRepository
{
private readonly WebDbContext _context;
public ArticleRepository(IWebDbContext context)
{
this._context = context as WebDbContext;
}
public Article Get(Guid id)
{
return _context.Articles.FirstOrDefault(x => x.Id == id);
}
public IEnumerable<Article> GetAll()
{
return _context.Articles;
}
public Article Add(Article item)
{
this._context.Articles.Add(item);
return item;
}
public void Update(Article item)
{
if (_context.Articles.Local.Select(x => x.Id == item.Id).Any())
{
throw new ApplicationException("Object already exists in context");
}
_context.Entry(item).State = EntityState.Modified;
}
public void Delete(Article item)
{
this._context.Articles.Remove(item);
}
}
}
6. Create a Class UnitOfWork to Manage Transaction
With the Entity Framework, most of the time SaveChanges()
is sufficient. This creates a transaction, or enlists in any ambient transaction, and does all the necessary work in that transaction.
using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
namespace UnityTutorials.Models
{
public partial interface IUnitOfWork : IDisposable
{
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly WebDbContext _context;
private readonly IDbTransaction _transaction;
private readonly ObjectContext _objectContext;
public UnitOfWork(IWebDbContext context)
{
this._context = context as WebDbContext ?? new WebDbContext();
this._objectContext = ((IObjectContextAdapter)this._context).ObjectContext;
if (this._objectContext.Connection.State != ConnectionState.Open)
{
this._objectContext.Connection.Open();
this._transaction = _objectContext.Connection.BeginTransaction();
}
}
public void Commit()
{
try
{
this._context.SaveChanges();
this._transaction.Commit();
}
catch (Exception)
{
Rollback();
throw;
}
}
private void Rollback()
{
this._transaction.Rollback();
foreach (var entry in this._context.ChangeTracker.Entries())
{
switch (entry.State)
{
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Deleted:
entry.State = EntityState.Unchanged;
break;
}
}
}
public void Dispose()
{
if (this._objectContext.Connection.State == ConnectionState.Open)
{
this._objectContext.Connection.Close();
}
}
}
}
7. Create a Class UnitOfWorkManage to Manage UnitOfWork
using System;
using System.Data.Entity;
namespace UnityTutorials.Models
{
public interface IUnitOfWorkManager : IDisposable
{
IUnitOfWork NewUnitOfWork();
}
public class UnitOfWorkManager : IUnitOfWorkManager
{
private bool _isDisposed;
private readonly WebDbContext _context;
public UnitOfWorkManager(IWebDbContext context)
{
Database.SetInitializer<WebDbContext>(null);
this._context = context as WebDbContext;
}
public IUnitOfWork NewUnitOfWork()
{
return new UnitOfWork(this._context);
}
public void Dispose()
{
if (this._isDisposed == false)
{
this._context.Dispose();
this._isDisposed = true;
}
}
}
}
8. Now, Test Our Unity
Step 1: Create a class called as BaseController
using System.Web.Mvc;
using UnityTutorials.Models;
namespace UnityTutorials.Controllers
{
public class BaseController : Controller
{
protected readonly IUnitOfWorkManager UnitOfWorkManager;
public BaseController(IUnitOfWorkManager unitOfWorkManager)
{
UnitOfWorkManager = unitOfWorkManager;
}
}
}
Step 2: Create a class called as ArticleController
using System;
using System.Web.Mvc;
using UnityTutorials.Models;
namespace UnityTutorials.Controllers
{
public class ArticleController : BaseController
{
private readonly IArticleRepository _articleRepository;
public ArticleController(IUnitOfWorkManager unitOfWorkManager, IArticleRepository articleRepository)
: base(unitOfWorkManager)
{
this._articleRepository = articleRepository;
}
public ActionResult Test()
{
using (var unitOfWork = this.UnitOfWorkManager.NewUnitOfWork())
{
this._articleRepository.Add(new Article()
{
Id = Guid.NewGuid(),
Title = "Title Text",
Summary = "Summary Text",
ArticleContent = "Html content",
ViewCount = 0,
CreatedDate = DateTime.Now,
CreatedByUsername = "admin",
Tags = "mvc, unity, asp.net"
});
unitOfWork.Commit();
}
return View();
}
}
}
9. Create Class Called as UnityMvc5 to Register Unity with ASP.NET MVC
Notes: Remember install Unity.Mvc5, using Nuget in Visual Studio to install: Install-Package Unity.Mvc5
You can reference: https://www.nuget.org/packages/Unity.Mvc5/
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Unity.Mvc5;
namespace UnityTutorials.Models
{
public static class IocExtensions
{
public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
}
public static void BindInSingletonScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
}
}
public class UnityMvc5
{
public static void Start()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.BindInRequestScope<IWebDbContext, WebDbContext>();
container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();
container.BindInRequestScope<IArticleRepository, ArticleRepository>();
return container;
}
}
}
10. Start Unity at Application_Start Event in Global.asax
Add line: UnityMvc5.Start();
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace UnityTutorials
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityMvc5.Start();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
Reference
The main references are given below:
Summary
I have put my time and efforts in all of my articles. Please don't forget to mark your votes, suggestions and feedback to improve the quality of this and upcoming articles. Thanks for reading.