ASP.NET MVC Unity实现依赖注入
这两天看Spring.net,看到了控制反转依赖注入,因为公司项目没有使用到spring.net,所以想学学关于ASP.NET MVC中的依赖注入,通过学习发现有两种方式,第一种就是微软自带Unity,还一种是一个比较简单的框架Ninject,我觉得应该差不多,目前只试了Unity,所以先来说Unity
Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题。构建一个成功应用程序的关键是实现非常松散的耦合设计。松散耦合的应用程序更灵活,更易于维护。这样的程序也更容易在开发期间进行测试。你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件。例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是否被授权执行更新。依赖注入技术,可确保客户类正确实例化和填充所有这些对象,尤其是在依赖可能是抽象的 。
原文地址:http://www.cnblogs.com/sixiangqimeng/p/3571849.html
示例1:根据接口依赖创建类
上边简单介绍了Unity的API。如果在没有注册的情况下Resolve一个类型会发生什么呢?
假设我们需要对日志进行处理。我们先声明一个接口ILogger:
public interface ILogger
{
void Write(string log);
}
我们可以有多种方法实现这个接口,我们假设希望写日志到文件中:
public class FileLogger:ILogger
{
#region ILogger Members
public void Write(string log)
{
Console.WriteLine("Write log in file.");
}
#endregion
}
我们在实际生活中对数据库的选择也是多种多样的。我们创建一个数据库的基类:
public class Database
{
}
创建一个派生类:
public class CustomerDatabase : Database
{
private ILogger _logger;
public CustomerDatabase(ILogger logger)
{
_logger = logger;
}
}
注意它的构造器的参数是ILogger类型。首先我们要创建一个Unity 容器:
UnityContainer container = new UnityContainer();
接下来我们需要在容器中注册一种类型,它是一个类型的映射,接口类型是ILogger,我希望返回的类型是FileLogger:
container.RegisterType<ILogger, FileLogger>();
然后我们使用Resolve 方法:
Database database = container.Resolve<CustomerDatabase>();
经过调试我们可以发现,如果在容器中没有注册的类型。执行Resolv方法后,Unity尝试创建该类型,会执行该类的构造器。最后database变量的类型就是CustomerDatabase,而且它的私有字段ILogger的当前实例也为FileLogger。
示例2:类型映射
我们希望返回一个日志类的实例,无论它是哪个实现类。我们可以直接在Resolve的类型中指定类型为接口ILogger:
UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, FileLogger>();
ILogger logger = container.Resolve<ILogger>();
每一次 container都会给我们返回一个新的logger实例。
示例3:单例模式的注册
如果我们想告诉Unity,我们想控制生命周期,我们想用单例模式。RegisterType方法包含一个重载,将使用LifetimeManager。每次我们在想获得到database实例时,unity总是会返回第一次我创建的CustomerDatabase。
UnityContainer container = new UnityContainer();
container.RegisterType<Database, CustomerDatabase>
(new ContainerControlledLifetimeManager());
示例4:注册时附带key
在我们向容器里注册时,可以附带一个string 类型的Key值。
UnityContainer container = new UnityContainer();
container.RegisterType<Database, SQLDatabase>("SQL");
container.RegisterType<Database, ORACLEDatabase>("ORACLE");
IEnumerable<Database> databases = container.ResolveAll<Database>();
Database database = container.Resolve<Database>("SQL");
我们分别向容器中注册了名为“SQL“和”ORACLE“的Database。当我们使用ResolverAll方法是。容器会返回容器中所有类型为Database的类。
这时我们如果仅仅想回去SQL的实例,我们可以使用container.Resolve<Database>("SQL");
//================================================================================================================================================//
上面的项目是网上借鉴的,下面自己写了一个项目实现依赖注入
//================================================================================================================================================//
这段是对封装的容器做进一步处理
using System; using System.Collections.Generic; using System.Web; using System.Web.Mvc; using Microsoft.Practices.Unity; namespace Unity.Mvc3 { public class UnityDependencyResolver : IDependencyResolver { private const string HttpContextKey = "perRequestContainer"; private readonly IUnityContainer _container; public UnityDependencyResolver(IUnityContainer container) { _container = container; } public object GetService(Type serviceType) { if (typeof(IController).IsAssignableFrom(serviceType)) { return ChildContainer.Resolve(serviceType); } return IsRegistered(serviceType) ? ChildContainer.Resolve(serviceType) : null; } public IEnumerable<object> GetServices(Type serviceType) { if (IsRegistered(serviceType)) { yield return ChildContainer.Resolve(serviceType); } foreach (var service in ChildContainer.ResolveAll(serviceType)) { yield return service; } } protected IUnityContainer ChildContainer { get { var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer; if (childContainer == null) { HttpContext.Current.Items[HttpContextKey] = childContainer = _container.CreateChildContainer(); } return childContainer; } } public static void DisposeOfChildContainer() { var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer; if (childContainer != null) { childContainer.Dispose(); } } private bool IsRegistered(Type typeToCheck) { var isRegistered = true; if (typeToCheck.IsInterface || typeToCheck.IsAbstract) { isRegistered = ChildContainer.IsRegistered(typeToCheck); if (!isRegistered && typeToCheck.IsGenericType) { var openGenericType = typeToCheck.GetGenericTypeDefinition(); isRegistered = ChildContainer.IsRegistered(openGenericType); } } return isRegistered; } } }
using System; using System.Diagnostics; namespace Unity.Mvc3.Example.Models { public class ExampleContext : IExampleContext, IDisposable { public ExampleContext() { Debug.WriteLine("ExampleContext Constructor"); } public string GetMessage() { Debug.WriteLine("ExampleContext GetMessage"); return "A message from the ExampleContext"; } public void Dispose() { Debug.WriteLine("ExampleContext Dispose"); } } }
namespace Unity.Mvc3.Example.Models { public interface IExampleContext { string GetMessage(); } }
namespace Unity.Mvc3.Example.Models { public class LowerCaseService : ILowerCaseService { private readonly IExampleContext _context; public LowerCaseService(IExampleContext context) { _context = context; } public string GetMessage() { return _context.GetMessage().ToLower(); } } } namespace Unity.Mvc3.Example.Models { public interface ILowerCaseService { string GetMessage(); } }
namespace Unity.Mvc3.Example.Models { public class UpperCaseService : IUpperCaseService { private readonly IExampleContext _context; public UpperCaseService(IExampleContext context) { _context = context; } public string GetMessage() { return _context.GetMessage().ToUpper(); } } } namespace Unity.Mvc3.Example.Models { public interface IUpperCaseService { string GetMessage(); } }
原文地址:http://www.cnblogs.com/sixiangqimeng/p/3571849.html
using System.Web.Mvc; using Unity.Mvc3.Example.Models; namespace Unity.Mvc3.Example.Controllers { public class HomeController : Controller { private readonly IUpperCaseService _upperCaseService; private readonly ILowerCaseService _lowerCaseService; public HomeController(IUpperCaseService upperCaseService, ILowerCaseService lowerCaseService) { _upperCaseService = upperCaseService; _lowerCaseService = lowerCaseService; } public ActionResult Index() { ViewBag.Message1 = _upperCaseService.GetMessage(); ViewBag.Message2 = _lowerCaseService.GetMessage(); return View(); } public ActionResult About() { ViewBag.Message = _upperCaseService.GetMessage(); return View(); } } }
protected void Application_Start() { RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); Bootstrapper.Initialise(); }