今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系、注册已存在的对象之间的关系,同时着重介绍 了Unity内置的各种生命周期管理器的使用方法,今天则主要介绍Unity的Register和Resolve的一些高级应用。

本篇文章将主要介绍:

1、注册类型同时初始化构造函数参数并重载调用。

2、注册类型同时初始化属性参数并重载调用。

3、延迟获取对象。

4、检索检索容器中注册信息。

一、注册类型同时初始化构造函数参数并重载调用

我们在使用Unity中注册对象之间的关系时,可能对象有相应的构造函数,构造函数中需要传递相应的参数,Unity就支持这样的注册,其主要靠InjectionConstructor这个类来完成,我们首先来看下具体的类构造函数:

  1. public YourClass(string test, MyClass my)
  2. {
  3. Console.WriteLine(test);
  4. Console.WriteLine(my.ToString());
  5. }

这个构造函数有2个参数,一个字符串和一个MyClass类对象,相应的可以使用如下代码进行注册:

  1. //由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
  2. //这边采用InjectionConstructor这个类来实现
  3. container.RegisterType<IClass, YourClass>(
  4. new InjectionConstructor("a", new MyClass()));
  5. Console.WriteLine("-----------默认调用输出-------------");
  6. container.Resolve<IClass>();

这样既可完成对象注册的同时对构造函数参数进行注入,此时还有另外一个需求,就是虽然在注册的时候已经对构造函数参数进行了初始化,但是在调用的时候我们想更换原先注册的值,这时应该怎么办?

在Unity中,已经帮我们解决了这个问题,我们可以通过ParameterOverride和ParameterOverrides来实现,其中 ParameterOverride是针对一个参数,而ParameterOverrides是针对参数列表,有关注册参数初始化及参数重载的全部代码如 下:

  1. public static void ResolveParameter()
  2. {
  3. //由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
  4. //这边采用InjectionConstructor这个类来实现
  5. container.RegisterType<IClass, YourClass>(
  6. new InjectionConstructor("a", new MyClass()));
  7. Console.WriteLine("-----------默认调用输出-------------");
  8. container.Resolve<IClass>();
  9.  
  10. Console.WriteLine("-----------重载后调用输出-------------");
  11. //以下2种Resolve方法效果是一样的
  12. //对于参数过多的时候可以采用第2种方法,如果参数仅仅只有1个可以用第1种
  13. //container.Resolve<IClass>(new ParameterOverride("test", "test"),
  14. // new ParameterOverride("my", "new MyClass").OnType<MyClass>());
  15. container.Resolve<IClass>(new ParameterOverrides()
  16. {
  17. {"test","test"},
  18. {"my",new MyClass()}
  19. }.OnType<YourClass>());

其中需要注意的是:

1、在使用ParameterOverride方法来重载参数时,如果注册的参数是一个具体的对象就需要使用OnType这个扩展方法来指定对应的类型,否则会报错。

2、在使用ParameterOverrides进行重载参数时,可以使用如上面代码的方式进行指定,但是同样需要使用OnType来指定,不过这个的OnType指定的类型是注册的对象类型。

效果图如下:

可以看出,其中第一个字符串参数在重载后调用时已经发生了更改。

二、注册类型同时初始化属性并重载调用

这个初始化属性和上面的初始化参数很类似,只不过不同的是,属性的注册初始化是使用InjectionProperty,而重载属性是使用的 PropertyOverride和PropertyOverrides,其使用方法也是相同的,这边就不多介绍了,代码如下:

  1. public static void ResolveProperty()
  2. {
  3. //注册对象关系时初始化对象的属性
  4. container.RegisterType<IClass, MyClass>(
  5. new InjectionProperty("Name", "A班"),
  6. new InjectionProperty("Description", "A班的描述"));
  7. Console.WriteLine("-----------默认调用输出-------------");
  8. Console.WriteLine(container.Resolve<IClass>().Name);
  9. Console.WriteLine(container.Resolve<IClass>().Description);
  10. Console.WriteLine("-----------重载后调用输出-------------");
  11. //以下2种写法效果是一样的,同上面的构造函数参数重载
  12. //var myClass = container.Resolve<IClass>(new PropertyOverride("Name", "重载后的A班"),
  13. // new PropertyOverride("Description", "重载后的A班的描述"));
  14. var myClass = container.Resolve<IClass>(new PropertyOverrides()
  15. {
  16. {"Name","重载后的A班"},
  17. {"Description","重载后的A班的描述"}
  18. }.OnType<MyClass>());
  19.  
  20. Console.WriteLine(myClass.Name);
  21. Console.WriteLine(myClass.Description);
  22. }

效果图如下:

可以看到2个属性都已经被重载了。

Unity还为我们提供了一个DependencyOverride重载,其使用方法和参数重载、属性重载类似,这边就不演示了,不过需要注意的是DependencyOverride是针对所注册对象类型中所包含的对象类型重载,例如在A类中有构造函数参数是B类,同时也有个属性依赖于B类,当使用了DependencyOverride后,这个A对象原先注册的有关B类的依赖将全部改变。(具体可查看示例代码中的ResolveDependency)

三、延迟获取对象

Unity还有个很不错的特性就是支持延迟获取, 其本质是通过事先建立一个委托,然后再调用这个委托,看下下面的代码:

  1. public static void DeferringResolve()
  2. {
  3. var resolver = container.Resolve<Func<IClass>>();
  4.  
  5. //根据业务逻辑做其他事情。
  6.  
  7. //注册IClass与MyClass之间的关系
  8. container.RegisterType<IClass, MyClass>();
  9. //获取MyClass实例
  10. var myClass = resolver();
  11.  
  12. var resolver2 = container.Resolve<Func<IEnumerable<IClass>>>();
  13.  
  14. //根据业务逻辑做其他事情。
  15.  
  16. //注册与IClass相关的对象。
  17. container.RegisterType<IClass, MyClass>("my");
  18. container.RegisterType<IClass, YourClass>("your");
  19. //获取与IClass关联的所有命名实例
  20. var classList = resolver2();
  21. }

这段代码演示了2个延迟获取的方式,都是通过将Func<T>放入Resolve<T>中来实现的,返回的是一委托,这样就可以在实际需要的时候再调用这个委托:

1、第一种是事先通过Resolve<Func<IClass>>(); 来定义获取与IClass关联的对象的委托,然后再注册IClass与MyClass之间的关系,然后再通过resolver(); 来获取。

2、第二种是事先通过Resolve<Func<IEnumerable<IClass>>>(); 来定义获取一个与IClass关联的命名实例列表的委托,然后调用相应的委托就可以一次性获取与IClass关联的所有命名实例。

这2种方式都很好的展示了Unity可以更加灵活的控制对象之间的注册与对象的调用。

四、检索容器中注册信息

当我们在不断使用Unity容器的过程中,我们有时候想看一下容器中到底注册了多少对象,以及各个对象的一些信息,如:什么对象和什么对象关联、具体的注 册名称和使用的生命周期管理器,这些信息都可以在容器的Registrations属性中查看到,在Unity文档中已经有个方法来查看这些信息了,代码 如下:

  1. public static void DisplayContainerRegistrations(IUnityContainer theContainer)
  2. {
  3. string regName, regType, mapTo, lifetime;
  4. Console.WriteLine("容器中 {0} 个注册信息:",
  5. theContainer.Registrations.Count());
  6. foreach (ContainerRegistration item in theContainer.Registrations)
  7. {
  8. regType = item.RegisteredType.Name;
  9. mapTo = item.MappedToType.Name;
  10. regName = item.Name ?? "[默认]";
  11. lifetime = item.LifetimeManagerType.Name;
  12. if (mapTo != regType)
  13. {
  14. mapTo = " -> " + mapTo;
  15. }
  16. else
  17. {
  18. mapTo = string.Empty;
  19. }
  20. lifetime = lifetime.Substring(, lifetime.Length - "生命周期管理器".Length);
  21. Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
  22. }
  23. }

具体的注册代码如下:

  1. public static void RegisterAll()
  2. {
  3. container.RegisterType<IClass, MyClass>("my");
  4. container.RegisterType<IClass, YourClass>("your",
  5. new ExternallyControlledLifetimeManager());
  6. container.RegisterType<ISubject, Subject1>("subject1");
  7. container.RegisterType<ISubject, Subject2>("subject2");
  8.  
  9. DisplayContainerRegistrations(container);
  10. }

效果图如下:

可以看到,我在代码中注册的信息都已经很好的反应出来了。

同时如果想查看某个对象是否已经被注册,可以通过container.IsRegistered<T>来验证,这边就不演示了。

以上就是本文的所有内容了,主要介绍了Unity的Register和Resolve的一些高级应用,英文好的朋友可以直接查看Unity的官方文档。

示例代码下载:点我下载

微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)的更多相关文章

  1. 微软企业库5.0 学习之路——第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息

    在介绍完企业库几个常用模块后,我今天要对企业库的配置文件进行处理,缘由是我打开web.config想进行一些配置的时候发现web.config已经变的异常的臃肿(大量的企业库配置信息充斥其中),所以决 ...

  2. 微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

    在上一篇文章中, 我介绍了企业库Cryptographer模块的一些重要类,同时介绍了企业库Cryptographer模块为我们提供的扩展接口,今天我就要根据这些 接口来进行扩展开发,实现2个加密解密 ...

  3. 微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证

    前端时间花了1个多星期的时间写了使用jQuery.Validate进行客户端验证,但是那仅仅是客户端的验证,在开发项目的过程中,客户端的信息永远是不可信的,所以我们还需要在服务器端进行服务器端的验证已 ...

  4. 微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)

    首先先补习下企业库的Caching Application Block的相关知识: 1.四大缓存方式,在Caching Application Block中,主要提供以下四种保存缓存数据的途径,分别是 ...

  5. 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

    一.独立验证器 我上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂 ...

  6. [EntLib]微软企业库5.0 学习之路——第一步、基本入门

    话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白). 直到去年在 ...

  7. 微软企业库5.0 学习之路——第二步、使用VS2010+Data Access模块建立多数据库项目

    现在我就开始进入学习之路的第二步——Data Access模块,这个模块是企业库中被使用频率最高的模块,它很好的封装了数据库操作应用,为我们进行多数据库系统开发提供了便利,只需更改配置文件就 可以很快 ...

  8. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  9. 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

    这篇文章是我在patterns & practices看到的一篇有关EntLib5.0的文章,主要介绍了EntLib5.0的这次的架构变化由来,觉得很不错,大家可以看一下! 在过去几年中,依赖 ...

随机推荐

  1. swagger2的常用注解,传递参数的注意使用方法

    背景介绍: 刚开始的时候,在controller层使用@RequestParam的时候,发现这个参数是必须要输入值的,但是我们有时候必须查询的时候允许参数为空,使用这个注解就不行了. 在集成了swag ...

  2. 装饰器--decorator3

    装饰器添加返回值 import time def timer(func): def wrapper(*args,**kwargs): #wrapper包装的意思 start_time = time.t ...

  3. 转:Unable to execute dex: Multiple dex files define 解决方法

    转自:http://blog.csdn.net/mxlxiao7/article/details/8978930 问题发生概述: 程序编译正常,在用Eclipse调试执行时,报错Unable to e ...

  4. HDU 4978 计算 凸包

    有以无限间隔$D$的水平线分割的平面,在上面随机投下一个圆,圆中有一些点,点之间两两成一条线段,问随机投下至少有一条线段于平行线相交的概率. 以下是不严(luan)谨(lai)的思路. 首先都知道对于 ...

  5. JAVA多线程基础学习三:volatile关键字

    Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个 ...

  6. Distributed Systems 分布式系统

    先来扯淡,几天是14年12月31日了,茫茫然,2014就剩最后一天了.这两天国大都放假,我给自己安排了四篇博客欠账,这就是其中的第一篇,简单介绍一些分布式系统的一些概念和设计思想吧.后面三篇分别是Ne ...

  7. Mock InjectMocks ( @Mock 和 @InjectMocks )区别

    之前一直对这两个注解的区别不是很明白. 搜到过一篇博客园的文章举例说明了代码行为的区别.后来在stackoverflow上看到一个问答简单明了的解释了这两个注解在定义上的区别: 在此翻译记录一下: / ...

  8. 解决 IE7 中 display:inline-block 失效的问题

    我们在做首页菜单选项的时候,通常会用 li 标签去做,通过对 li 标签设置样式: display:inline-block 可以让 li 标签横排显示.但是这样做,在 IE7 浏览器下面会有一个兼容 ...

  9. perl6 单线程破解phpmyadmin脚本

    use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; my $url = 'http://localhost/phpMyAdmin/index.php' ...

  10. Spring是什么+控制反转和依赖注入

    Spring是一个开源框架,是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 原因: (1)通过控制反转(IOC)达到松耦合,IOC也就是把控制权交出去,在使用中直接得到对象 (2)提 ...