zoukankan      html  css  js  c++  java
  • (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

    原文地址:http://www.cnblogs.com/kyo-yo/archive/2010/11/22/Learning-EntLib-Tenth-Decoupling-Your-System-Using-The-Unity-PART2-Learn-To-Use-Unity-Three.html

          今天继续介绍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是针对参数列表,有关注册参数初始化及参数重载的全部代码如下:

    01 public static void ResolveParameter()
    02 {
    03     //由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
    04     //这边采用InjectionConstructor这个类来实现
    05     container.RegisterType<IClass, YourClass>(
    06         new InjectionConstructor("a", new MyClass()));
    07     Console.WriteLine("-----------默认调用输出-------------");
    08     container.Resolve<IClass>();
    09   
    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>());
    20 }

    其中需要注意的是:

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

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

    效果图如下:

    pic78

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

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

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

    01 public static void ResolveProperty()
    02 {
    03     //注册对象关系时初始化对象的属性
    04     container.RegisterType<IClass, MyClass>(
    05         new InjectionProperty("Name", "A班"),
    06         new InjectionProperty("Description", "A班的描述"));
    07     Console.WriteLine("-----------默认调用输出-------------");
    08     Console.WriteLine(container.Resolve<IClass>().Name);
    09     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 }

    效果图如下:

    pic79

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

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

    三、延迟获取对象

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

    01 public static void DeferringResolve()
    02 {
    03     var resolver = container.Resolve<Func<IClass>>();
    04   
    05     //根据业务逻辑做其他事情。
    06   
    07     //注册IClass与MyClass之间的关系
    08     container.RegisterType<IClass, MyClass>();
    09     //获取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文档中已经有个方法来查看这些信息了,代码如下:

    01 public static void DisplayContainerRegistrations(IUnityContainer theContainer)
    02 {
    03     string regName, regType, mapTo, lifetime;
    04     Console.WriteLine("容器中 {0} 个注册信息:",
    05             theContainer.Registrations.Count());
    06     foreach (ContainerRegistration item in theContainer.Registrations)
    07     {
    08         regType = item.RegisteredType.Name;
    09         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(0, lifetime.Length - "生命周期管理器".Length);
    21         Console.WriteLine("+ {0}{1}  '{2}'  {3}", regType, mapTo, regName, lifetime);
    22     }
    23 }

    具体的注册代码如下:

    01 public static void RegisterAll()
    02 {
    03     container.RegisterType<IClass, MyClass>("my");
    04     container.RegisterType<IClass, YourClass>("your"
    05         new ExternallyControlledLifetimeManager());
    06     container.RegisterType<ISubject, Subject1>("subject1");
    07     container.RegisterType<ISubject, Subject2>("subject2");
    08   
    09     DisplayContainerRegistrations(container);
    10 }

    效果图如下:

    pic80

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

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

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

    示例代码下载:点我下载

    注意:本文示例代码是基于VS2010+Unity2.0,所以请使用VS2010打开,如果没有安装VS2010,请将相关代码复制到相应的VS中运行既可

    微软企业库5.0 学习之路系列文章索引:

    第一步、基本入门

    第二步、使用VS2010+Data Access模块建立多数据库项目

    第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中)

    第四步、使用缓存提高网站的性能(EntLib Caching)

    第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇

    第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——中篇

    第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

    第六步、使用Validation模块进行服务器端数据验证

    第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇

    第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

    第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息

    第九步、使用PolicyInjection模块进行AOP—PART1——基本使用介绍

    第九步、使用PolicyInjection模块进行AOP—PART2——自定义Matching Rule

    第九步、使用PolicyInjection模块进行AOP—PART3——内置Call Handler介绍

    第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?

    第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)

    第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)

    第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

    第十步、使用Unity解耦你的系统—PART3——依赖注入

    扩展学习:

    扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

    作者:kyo-yo
    出处:http://kyo-yo.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     

  • 相关阅读:
    【LG3231】[HNOI2013]消毒
    【LG3230】[HNOI2013]比赛
    【LG3236】[HNOI2014]画框
    【BZOJ3142】[HNOI2013]数列
    【BZOJ2395】[Balkan 2011]Timeismoney
    【CF613D】Kingdom and its Cities
    【LG4103】[HEOI2014]大工程
    【LG3320】[SDOI2015]寻宝游戏
    【LG4841】城市规划
    【CF960G】Bandit Blues
  • 原文地址:https://www.cnblogs.com/fcsh820/p/1891312.html
Copyright © 2011-2022 走看看