[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:

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

本篇文章将主要介绍:

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

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

3、延迟获取对象。

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

 

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

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

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

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

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

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

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

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

其中需要注意的是:

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

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

效果图如下:

pic78

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

 

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

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

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

效果图如下:

pic79

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

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

 

三、延迟获取对象

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

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

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

具体的注册代码如下:

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

效果图如下:

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——依赖注入

第十步、使用Unity解耦你的系统—PART4——Unity&PIAB

扩展学习:

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



本文转自kyo-yo博客园博客,原文链接: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,如需转载请自行联系原作者


目录
相关文章
|
2月前
|
图形学 开发者 UED
Unity游戏开发必备技巧:深度解析事件系统运用之道,从生命周期回调到自定义事件,打造高效逻辑与流畅交互的全方位指南
【8月更文挑战第31天】在游戏开发中,事件系统是连接游戏逻辑与用户交互的关键。Unity提供了多种机制处理事件,如MonoBehaviour生命周期回调、事件系统组件及自定义事件。本文介绍如何有效利用这些机制,包括创建自定义事件和使用Unity内置事件系统提升游戏体验。通过合理安排代码执行时机,如在Awake、Start等方法中初始化组件,以及使用委托和事件处理复杂逻辑,可以使游戏更加高效且逻辑清晰。掌握这些技巧有助于开发者更好地应对游戏开发挑战。
93 0
|
3月前
|
图形学 C# 开发者
Unity粒子系统全解析:从基础设置到高级编程技巧,教你轻松玩转绚丽多彩的视觉特效,打造震撼游戏画面的终极指南
【8月更文挑战第31天】粒子系统是Unity引擎的强大功能,可创建动态视觉效果,如火焰、爆炸等。本文介绍如何在Unity中使用粒子系统,并提供示例代码。首先创建粒子系统,然后调整Emission、Shape、Color over Lifetime等模块参数,实现所需效果。此外,还可通过C#脚本实现更复杂的粒子效果,增强游戏视觉冲击力和沉浸感。
141 0
|
3月前
|
开发者 图形学 前端开发
绝招放送:彻底解锁Unity UI系统奥秘,五大步骤教你如何缔造令人惊叹的沉浸式游戏体验,从Canvas到动画,一步一个脚印走向大师级UI设计
【8月更文挑战第31天】随着游戏开发技术的进步,UI成为提升游戏体验的关键。本文探讨如何利用Unity的UI系统创建美观且功能丰富的界面,包括Canvas、UI元素及Event System的使用,并通过具体示例代码展示按钮点击事件及淡入淡出动画的实现过程,助力开发者打造沉浸式的游戏体验。
79 0
|
3月前
|
图形学
Unity动画☀️Unity动画系统Bug集合
Unity动画☀️Unity动画系统Bug集合
|
4月前
|
数据可视化 vr&ar C#
|
5月前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
136 2
|
5月前
|
Rust 图形学
【unity实战】使用unity制作一个类似Rust的3D生存建造建筑系统,具有很好的吸附性(附项目源码)
【unity实战】使用unity制作一个类似Rust的3D生存建造建筑系统,具有很好的吸附性(附项目源码)
109 1
|
5月前
|
图形学
【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱10(附带项目源码)
【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱10(附带项目源码)
42 1
|
5月前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
77 0
|
5月前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
71 0