转载于:http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html

家人身体不太好,好几天没在园子里发帖了。

新项目还是要用MVC3,team 计划使用 Unity。看了一下网上的资料,都是比较老的了,官网也没什么好的指引。MVC也在更新,Unity也在更新。花了1天半时间去MSDN,P&P查资料,整理了一下分享给大家。言归正传:

什么是Unity?

Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题。构建一个成功应用程序的关键是实现非常松散的耦合设计。松散耦合的应用程序更灵活,更易于维护。这样的程序也更容易在开发期间进行测试。你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件。例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是否被授权执行更新。依赖注入技术,可确保客户类正确实例化和填充所有这些对象,尤其是在依赖可能是抽象的 。

如何得到Unity?

您可以访问http://unity.codeplex.com/releases得到最新版本的Unity现在。当然,如果您在您的visual studio 中安装了Nuget 包管理器,你可以直接在Nuget中获取到最新版本的Unity。

API

UnityContainer.RegisterType<ITFrom,TTO>();

UnityContainer.RegisterType< ITFrom, TTO >();

UnityContainer.RegisterType< ITFrom, TTO >("keyName");

IEnumerable<T> databases = UnityContainer.ResolveAll<T>();

IT instance = UnityContainer.Resolve<IT>();

T instance = UnityContainer.Resolve<T>("keyName");

UnitContainer.RegisterInstance<T>("keyName",new T());

UnityContainer.BuildUp(existingInstance);

IUnityContainer childContainer1 = parentContainer.CreateChildContainer();

代码举例

在开始之前我们要先做一些准备工作。首先创建一个控制台应用程序。使用Nuget 添加Unity到当前项目中。我们可以发现,dll引用中多了3个dll:Microsoft.Practices.ServiceLocation, Microsoft.Practices.Unity和Microsoft.Practices.Configuation。

示例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");

示例5:注册已经存在的实例

通过下边方式我们可以在container中注册一个实例:

  UnityContainer container = new UnityContainer();  container.RegisterInstance<Database>(new SQLDatabase());  container.RegisterInstance<Database>("Oracle", new ORACLEDatabase());  Database database = container.Resolve<Database>();  Database oracleDatabase = container.Resolve<Database>("Oracle");

看起来和上边的方式没什么不同。重要的是,当我们使用RegisterInstance方法时,Unity会注册一个单例。

我们还有一种方法可以把已经存在的实例注入到容器中。

             UnityContainer container = new UnityContainer();             container.RegisterType<ILogger, FileLogger>();             SQLDatabase existDatabase = new SQLDatabase();             container.BuildUp(existDatabase);             container.RegisterInstance<Database>(existDatabase);             Database database = container.Resolve<Database>();

就如上边代码中,我们已经存在一个database 是DB2Database。你希望Unity做的是把依赖注入到容器中。

我们用BuildUp方法告诉Unity我们的想法。这时候Unity回去DB2Database 类,如果他发现了[Dependency]这个特性。他就自动的把我们前边注册的FileLogger注入到DB2Database的Logger字段中。

以下是DB2Database类:

public class DB2Database:Database    {        [Dependency]        public ILogger Logger { get; set; }    }

使用配置文件来实现关系映射

我们也可以再web.config里配置 文件的依赖关系映射。首先我打开web.config文件。按照如下结构添加section。这里我只是简单的映射了ILogger 接口和FileLogger。并且指定了生命周期是单例。

<configuration>  <configSections>    <section name="unity"             type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,                Microsoft.Practices.Unity.Configuration"/>  </configSections>  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">    <container name="containerOne">      <types>        <type type="UnityDemo_ConsoleApplication.ILogger" mapTo="UnityDemo_ConsoleApplication.FileLogger"              lifeTime="Singleton"/>      </types>

    </container>

  </unity>......</configuration>

如果你想更详细的了解元素和属性的使用,可以看以下Unity 在xml中配置的结构图:

更详细了解,请参见:

http://msdn.microsoft.com/en-us/library/ff647848.aspx

http://msdn.microsoft.com/zh-cn/library/dd203230.aspx

如何读取配置 并加载

Unity同样支持我们在配置文件里写设定映射关系。

首先我们要引入命名空间: Microsoft.Practices.Unity.Configuration;

在Unity2.0以上版本,已经废弃了以前的方法。现在我们有2种方式可以读取配置。

第一种,我们使用configurationManager:

引用命名空间:System.Configuration

            IUnityContainer myContainer = new UnityContainer();

            myContainer.LoadConfiguration("containerOne ");            UnityConfigurationSection section                = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");            section.Configure(myContainer, "containerOne");

第二种,我们可以直接用容器读取配置信息:

IUnityContainer myContainer = new UnityContainer();
myContainer.LoadConfiguration("containerName");

通过 Injection API 指定依赖

假设我们有一个类GenericDatabase:

public class GenericDatabase:Database    {        private string _connectionString;        public ILogger Logger { get; set; }

        public GenericDatabase(string connectionString)        {            _connectionString = connectionString;        }    }

在这里我们要通过Injection API 来为这个类注入connectionString 和 Logger。

首先我们还和前边的一样注册映射关系:

            IUnityContainer container = new UnityContainer();            container.RegisterType<ILogger, FileLogger>();            container.RegisterType<Database, GenericDatabase>();

然后通过Injection API 为GenericDatabase注入ConnectionStrings和Logger:

container.Configure<InjectedMembers>()                .ConfigureInjectionFor<GenericDatabase>(                new InjectionConstructor(                    ConfigurationManager.ConnectionStrings["ConnectionStrings"] == null                     ? "defaultConnectionString" : ConfigurationManager.ConnectionStrings["ConnectionStrings"].ConnectionString),                    new InjectionProperty("Logger")            );            Database database = container.Resolve<Database>();

这样我们最后获得的database 就包含了connection 和 Logger。

嵌套式容器

容器是可以嵌套的,获取实例时遵循的规则是,如果子容器里不包含需要的对象,则会去父容器获取。如果有,则从自己里获取。

一旦父容器销毁,子容器也随之销毁。

UnityContainer parentContainer = new UnityContainer();            IUnityContainer childContainer1 = parentContainer.CreateChildContainer();            IUnityContainer childContainer2 = parentContainer.CreateChildContainer();            parentContainer.RegisterType<ILogger, FileLogger>(new ContainerControlledLifetimeManager());            childContainer1.RegisterType<ILogger, EventLogger>(new ContainerControlledLifetimeManager());            //应该从parentContainer得到FileLogger            ILogger logger = childContainer2.Resolve<ILogger>();            logger.Write("Test");            //应该从自己本身得到eventLogger

            ILogger logger2 = childContainer1.Resolve<ILogger>();

在MVC 中使用Unity注入Controller

在MVC2中我们会写一个controlleFactory 继承自DefaultControllerFactory。

并且override GetControllerInstance()这个方法。

MVC3对于依赖注入提供更好的支持。我们可以使用- IDependencyResolver 和 IControllerActivator 来实现对controller的注入。

具体实现如下:

创建一个MVC3项目。

我们要实现MVC3中新提供 的两个接口:IDependencyResolver和IControllerActivator

IDependencyResolver公开两个方法 - GetService的GetServices.The GetService方法解决了单独注册的服务,支持任意对象的创建,GetServices解决注册多个服务。IDependencyResolver接口的实现应该委托给底层的依赖注入容器提供注册服务请求的类型。当有没有注册的服务请求的类型,ASP.NET MVC框架预计这个接口的实现返回GetService为空,并从GetServices返回空集合。让我们以统一提供依赖注入工作IDependencyResolver intreface派生创建一个自定义的依赖解析器类。

我们定义一个类名为UnityDependencyResolver:

  public class UnityDependencyResolver : IDependencyResolver    {        IUnityContainer container;        public UnityDependencyResolver(IUnityContainer container)        {            this.container = container;        }

        public object GetService(Type serviceType)        {            try            {                return container.Resolve(serviceType);            }            catch            {                return null;            }        }

        public IEnumerable<object> GetServices(Type serviceType)        {            try            {                return container.ResolveAll(serviceType);            }            catch            {                return new List<object>();            }        }    }

实现两个方法GetService和GetServices。使用Unity容器返回我们需要的Service或者ojbect。

实现两个方法GetService和GetServices。使用Unity容器返回我们需要的Service或者ojbect。

ASP.NET MVC 3已经推出了一个新的接口IControllerActivator,让您激活与自定义的行为控制器,并且可以使用依赖注入.让我们创建一个派生自IControllerActivator 接口的一个自定义的控制器

IController IControllerActivator.Create( System.Web.Routing.RequestContext requestContext,            Type controllerType)        {            return DependencyResolver.Current                .GetService(controllerType) as IController;        }

DependencyResolver.Current.GetService会执行我们自己定义的UnityDependencyResolver中的方法。

定义好这两个类,我们找到Global.asax.cs,并在其中中添加一个私有方法GetUnityContainer():

        private IUnityContainer GetUnityContainer()        {            //Create UnityContainer                      IUnityContainer container = new UnityContainer()            .RegisterType<IControllerActivator, CustomControllerActivator>()            .RegisterType<ILogger, FlatFileLogger>();            return container;        }

这个方法定义了一个新的容器。并且注册了映射关系。我们要返回的container中包含:CustomControllerActivator和FlatFileLogger。

IUnityContainer container = GetUnityContainer();

DependencyResolver.SetResolver(new UnityDependencyResolver(container));

上边的都做好了。我们在Application_Start方法中添加如下代码:

protected void Application_Start()        {            ...            IUnityContainer container = GetUnityContainer();            DependencyResolver.SetResolver(new UnityDependencyResolver(container));        }

首先我们通过GetUnityContainer方法获得container,并且设置当前的Resolver是我们自己实现的UnityDependencyResolver。

在Controller中我们只需要添加一个[Dependency]特性,就可以很方便的获取到我们注入的Logger。

  public class HomeController : Controller    {        [Dependency]        public ILogger Logger { get; set; }

        public ActionResult Index()        {

            ViewBag.Message = "Welcome to ASP.NET MVC!";

            Logger.GetType();

            return View();        }

        public ActionResult About()        {            return View();        }    }

我们可以使用Logger.GetType()查看到,我们当前的Logger就是我们之前注册的FlatFileLogger。

参考资料

http://unity.codeplex.com/

http://www.cnblogs.com/Terrylee/archive/2008/02/21/unity-application-block-part1.html

http://msdn.microsoft.com/zh-cn/library/ff663144.aspx

http://www.martinfowler.com/articles/injection.html

http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx

http://www.pnpguidance.net/Screencast/UnityDependencyInjectionIoCScreencast.aspx

http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx

http://msdn.microsoft.com/en-us/library/ff660878(v=pandp.20).aspx

http://msdn.microsoft.com/zh-cn/library/dd203182.aspx

示例代码下载

转载于:https://www.cnblogs.com/0to9/p/9564878.html

【ASP.Net MVC3 】使用Unity 实现依赖注入相关推荐

  1. MVC3 中使用Unity实现依赖注入

    前言:前段时间一直在研究依赖注入,不过不是在MVC框架中使用,今天突然想到在MVC中使用Unity实现依赖注入,一时慌了,不知道从何下手,接着就是网上不停的找资料,下面我把我找到的资料分享下,也把我的 ...

  2. ASP.NET Core Filter如何支持依赖注入

    概述 通过使用 ASP.NET Core 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码.内置筛选器处理任务,例如:授权(防止用户访问未获授权的资源).响应缓存(对请求管道进行短路出路,以 ...

  3. ASP.NET Core技术研究-探秘依赖注入框架

    ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务.提供服务.依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者. 毫不夸张的说,ASP.NET ...

  4. [ASP.NET Core 3框架揭秘] 依赖注入:依赖注入模式

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架之中以实现对流程的复用,并按照"好莱坞法则"实现应用程序的代码与框架之间的交互.我们可以采用若干设计模式 ...

  5. Entity Framework 实体框架的形成之旅--利用Unity对象依赖注入优化实体框架(2)

    在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...

  6. ASP.NET CORE 第四篇 依赖注入IoC学习 + AOP界面编程初探

    原文作者:老张的哲学 更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjo ...

  7. ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起

    我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点.由于前面两章已经涵盖了依赖注入在管道构建过程中以及管道在处理请求过程的应用,但是内 ...

  8. Asp.Net.Core 系列-中间件和依赖注入进阶篇

    上一节讲了中间件和依赖注入的基础,紧接着: 中间件是怎么使用的?使用步骤是什么? 只要把中间件注册到管道中就行了,可以借助Startup对象(DelegateStartup或者ConventionBa ...

  9. Asp.net Core 自带DI依赖注入

    一.新增依赖注入类DIIoc /// <summary>/// DI依赖注入/// </summary>public class DIIoc{public static voi ...

最新文章

  1. 新一代的编译工具 SWC,97年小哥写的~
  2. 原生JS实现的DOM操作笔记(草稿整理)
  3. 数据库方面的操作示例
  4. 2019年中国IaaS公有云市场排名及份额出炉
  5. 回到顶部 jquery
  6. iOS图形学(四):iOS中的绘图框架
  7. scratch高级进阶的游戏项目分享:(知识的综合应用),含项目源文件百度云盘链接
  8. MYSQL建表语句转换成oracle建表语句
  9. 1. Packet sniffers (包嗅探器 14个)
  10. 通过c#打开pdf文件
  11. 这个是我18年整理的,之前在我的电子笔记,现在感觉还是需要分享写写博客大家互相学习更好
  12. Vue页面如何~及时更新页面数据
  13. 2022-2028全球与中国无线和多室音频市场现状及未来发展趋势
  14. 液晶LCD1602驱动代码
  15. 在Xml中加注释的方法
  16. win7下搭建小程序服务器,重磅!微信PC端支持小程序直接开启 适配Win7及以上系统...
  17. Https中公私钥加密算法和其使用的RSA算法分析
  18. 知云文献翻译安装及使用教程
  19. Kubernetes安装系列之Dashboard安装
  20. 【模块】更新ESP32连接PS4手柄,PS4手柄控制遥控车,遥控车控制方案

热门文章

  1. python读取大文件太慢_强悍的Python读取大文件的解决方案
  2. 程序员修炼之道 pdf_程序员修炼之道-注重实效
  3. c语言的基本数据类型和表达式,C语言–基本数据类型和表达式.ppt
  4. 回顾︱DeepAR 算法实现更精确的时间序列预测(二)
  5. arraylist的remove()循环删除问题
  6. php编程之如何调用支付宝支付接口的实现
  7. Silverlight 游戏开发小技巧:昼夜交替动画
  8. asp.net mvc 实现上传文件带进度条
  9. 使用valgrind检查cache命中率
  10. careercup-链表 2.4