微软企业库4.1学习笔记(二十五)Unity依赖注入模块2

  Unity模块的亮点

  Unity模块包括了下面的特点

  •   提供了一个创建对象,以及依赖的对象的方法
  •   提供的RegisterType方法用来在容器中注册类型和映射,Resolve方法可以返回任何依赖对象的实例。
  •   提供控制反转IOC功能,通过预先配置注入类的对象来实现。你可以在构造函数中指明一个类或者接口(构造函数注入),或者是使用attribute的属性注入,和方法调用注入。
  •   支持容器继承,容器可以有子容器,支持对象从子容器传递到父容器中。
  •   可以从标准的配置文件中读取信息,例如xml文件
  •   对类的定义没有任何要求。在类上不需要添加attribute(除非使用属性注入或者是方法调用注入),在类声明中没有任何限制。
  •   支持自定义容器,例如,你可以在方法中实现额外的对象构造,和容器功能,例如容器的缓存功能。

  什么时候使用Unity模块

  依赖注入提供了简化代码的机会,抽象对象之间的依赖,自动产生依赖对象的实例。但是,处理的过程对性能上有一点小的损失,而且可能会使得只需要简单依赖的地方变得复杂。

  通常来说,在下列情况你应该使用Unity模块:

  •   对象和类与其他对象和类有依赖关系。
  •   你的依赖关系是复杂的,或者是需要抽象。
  •   你需要构造函数、方法、或者是属性注入的功能。
  •   你需要管理对象实例的生命周期。
  •   你需要在运行的时候可以配置和改变依赖关系。
  •   你需要在web应用中缓存或者是持久化依赖关系。

  在下面的情况,你不应该使用Unity模块

  •   你的对象和类与其他的对象和类没有依赖关系。
  •   你的依赖关系很简单,不需要抽象。

  在开发的过程中使用Unity模块

  这个主题描述如何在应用开发中使用Unity模块。如何创建对象实例。

  使用Unity模块的系统需要

  最小需要如下:

  •   Microsoft Windows XP Professional,Windows Server 2003,Windows Server 2008 or Windows Vista operating System。
  •   Microsoft .NET Framework 2.0,3.0 or 3.5。
  •   Microsoft Visual Studio 2005 or 2008 development system。

  配置Unity模块

  Unity模块可以从xml配置文件中读取配置信息。默认情况下,就是应用中的app.config或者是web.config文件。你也可以从其他xml文件,或者是其他来源加载配置信息。

  在运行的时候配置容器

  1.格式化Unity配置文件

  下面的xml格式就是Unity的配置格式。

  

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> < configuration >  
  < configSections >  
    < section  name ="unity"  type ="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"   />
    </ configSections >  
  < unity >  ... ... 
  </ unity >  ... ... 
</ configuration >

   下面是一个比较完整的配置文件

  

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> <? xml version="1.0" encoding="utf-8"  ?>  
< configuration >  
  < configSections >  
    < section  name ="unity"  type ="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft patterns & practices – Unity Application Block 1.2 – October 2008 27
Microsoft.Practices.Unity.Configuration, =1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  />  
  </ configSections >
    < unity >  
    < typeAliases >   <!--  Lifetime manager types  -->  
      < typeAlias  alias ="singleton"  type ="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity"   />  
      < typeAlias  alias ="perThread"  type ="Microsoft.Practices.Unity.PerThreadLifetimeManager, Microsoft.Practices.Unity"   />
        < typeAlias  alias ="external"  type ="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity"   />   <!--  User-defined type aliases  -->  
      < typeAlias  alias ="IMyInterface"  type ="MyApplication.MyTypes.MyInterface, MyApplication.MyTypes"   />  
      < typeAlias  alias ="MyRealObject"  type ="MyApplication.MyTypes.MyRealObject, MyApplication.MyTypes"   />  
      < typeAlias  alias ="IMyService"  type ="MyApplication.MyTypes.MyService, MyApplication.MyTypes"   />  
      < typeAlias  alias ="MyDataService"  type ="MyApplication.MyTypes.MyDataService, MyApplication.MyTypes"   />  
      < typeAlias  alias ="MyCustomLifetime"  type ="MyApplication.MyLifetimeManager, MyApplication.MyTypes"   />  
    </ typeAliases >  
    < containers >  
      < container  name ="containerOne" >  
        < types >   <!--  Type mapping with no lifetime – defaults to "transient"  -->  
          < type  type ="Custom.MyBaseClass"  mapTo ="Custom.MyConcreteClass"   />   <!--  Type mapping using aliases defined above  -->  
          < type  type ="IMyInterface"  mapTo ="MyRealObject"  name ="MyMapping"   />   <!--  Lifetime managers specified using the type aliases  -->  
          < type  type ="Custom.MyBaseClass"  mapTo ="Custom.MyConcreteClass" >   < lifetime  type ="singleton"   />   </ type >
28 Microsoft patterns & practices – Unity Application Block 1.2 – October 2008
< type  type ="IMyInterface"  mapTo ="MyRealObject"  name ="RealObject" >   < lifetime  type ="perThread"   />   </ type >   < type  type ="IMyInterface"  mapTo ="MyRealObject"  name ="RealObject" >   < lifetime  type ="external"   />   </ type >   <!--  Lifetime manager specified using the full type name  -->   <!--  Any initialization data specified for the lifetime manager  -->   <!--  will be converted using the default type converter  -->   < type  type ="Custom.MyBaseClass"  mapTo ="Custom.MyConcreteClass" >   < lifetime  value ="sessionKey"  type ="MyApplication.MyTypes.MyLifetimeManager, MyApplication.MyTypes"   />   </ type >   <!--  Lifetime manager initialization using a custom TypeConverter  -->   < type  type ="IMyInterface"  mapTo ="MyRealObject"  name ="CustomSession" >   < lifetime  type ="MyCustomLifetime"  value ="ReverseKey"  typeConverter ="MyApplication.MyTypes.MyTypeConverter, MyApplication.MyTypes"   />   </ type >   <!--  Object with injection parameters defined in configuration  -->   <!--  Type mapping using aliases defined above  -->   < type  type ="IMyService"  mapTo ="MyDataService"  name ="DataService" >   < typeConfig  extensionType ="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration" >   < constructor >   < param  name ="connectionString"  parameterType ="string" >   < value  value ="AdventureWorks" />   </ param >   < param  name ="logger"  parameterType ="ILogger" >   < dependency  />   </ param >   </ constructor >   < property  name ="Logger"  propertyType ="ILogger"   />   < method  name ="Initialize" >   < param  name ="connectionString"  parameterType ="string" >   < value  value ="contoso" />   </ param >   < param  name ="dataService"  parameterType ="IMyService" >   < dependency  />   </ param >   </ method >   </ typeConfig >   </ type >
Microsoft patterns & practices – Unity Application Block 1.2 – October 2008 29
</ types >   < instances >   < add  name ="MyInstance1"  type ="System.String"  value ="Some value"   />   < add  name ="MyInstance2"  type ="System.DateTime"  value ="2008-02-05T17:50:00"   />   </ instances >   < extensions >   < add  type ="MyApp.MyExtensions.SpecialOne"   />   </ extensions >   < extensionConfig >   < add  name ="MyExtensionConfigHandler"  type ="MyApp.MyExtensions.SpecialOne.ConfigHandler"   />   </ extensionConfig >
      </ container >   <!--  ... more containers here ...  -->   </ containers >  
  </ unity >  
</ configuration >

 

  将配置信息加载到容器中

  Unity不会自动读取配置信息来创建和准备好一个容器。你需要在应用中用代码来初始化容器,你也可以用代码注册类型,类型映射,任何从文件中读取的扩展信息都可以用代码来创建。

  如果配置定义了一个未命名的容器,这个没有名字的容器就是默认的容器。你也可以给容器命名。你可以将每一个容器的配置信息加载到容器中,

  下面的代码就是初始化一个新的容器,然后加载配置文件中配置的类型,映射,和扩展定义。

  

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> IUnityContainer container  =   new  UnityContainer(); 
UnityConfigurationSection section  =  (UnityConfigurationSection)ConfigurationManager.GetSection( " unity " ); 
section.Containers.Default.Configure(container);

 

  加载容器的时候,你也可以使用容器的名称进行加载。下面的代码就是加载了一个名为containerOne的容器。

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> IUnityContainer container  =   new  UnityContainer();
 UnityConfigurationSection section  =  (UnityConfigurationSection)ConfigurationManager.GetSection( " unity " ); 
section.Containers[ " containerOne " ].Configure(container);
  

 

  创建一个在配置文件中定义的有继承关系嵌套的容器,你可以用CreateChildContainer方法加载每一个适当的容器信息。

  

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> IUnityContainer parentContainer  =   new  UnityContainer(); 
IUnityContainer childContainer  =  parentContainer.CreateChildContainer(); 
UnityConfigurationSection section 
=  (UnityConfigurationSection)ConfigurationManager.GetSection( " unity " ); 
section.Containers[ " containerOne " ].GetConfigCommand().Configure(parentContainer); 
section.Containers[ " nestedChildContainer " ].Configure(childContainer);

 

 

  你不能在配置文件中嵌套容器,在containers节中的所有container元素都是同一个级别的元素。容器嵌套是通过代码来创建,并且加载适当的容器。

  使用可替代的配置源

  如果有需要的话,你可以使用任何xml文件或者是其他源作为配置信息。例如,你可以用System.Configuration.Configuration类获取任何xml文件的配置信息,下面的代码中就是这样用的。

  

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> ExeConfigurationFileMap map  =   new  ExeConfigurationFileMap();
 map.ExeConfigFilename  =   " MyConfig.config "
System.Configuration.Configuration config  =  ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
 UnityConfigurationSection section  =  (UnityConfigurationSection)config.GetSection( " unity " );
 IUnityContainer container  =   new  UnityContainer();
 section.Containers[ " myContainer " ].Configure(container);

 

  配置支持数组

  Unity支持设计时数组参数,和运行是数组参数。

  在设计的时候配置支持数组参数

  在配置文件中使用array元素作为list的代表。array元素描述了一个包含注册实例和类型映射的数组。array可以嵌套使用,包含下面三个子元素:

  •   array
  •   dependency
  •   value
    ExpandedBlockStart.gif 代码
    <!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> < typeAlias  alias ="ILoggerArray"  type ="Microsoft.Practices.Unity.TestSupport.ILogger[], TestSupport.Unity"   />  
  • < typeAlias  alias ="ArrayConstructor"  type ="Microsoft.Practices.Unity.TestSupport.ObjectArrayConstructorDependency, Tests.Unity.Configuration"   />   </ typeAliases >  
  • < containers >   < container  name ="emptyArray" >   < types >   < type  type ="ArrayConstructor" >   < typeConfig  >   < constructor >   < param  name ="loggers"  parameterType ="ILoggerArray" >   < array  />   </ param >   </ constructor >   </ typeConfig >   </ type >
    Microsoft patterns & practices – Unity Application Block 1.2 – October 2008 33
    </ types >   </ container >

     

 

  下面的配置文件使用dependency子元素描述了获取指定类型的实例

  

 

ExpandedBlockStart.gif 代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> < typeAliases >  
  < typeAlias  alias ="ILogger"  type ="Microsoft.Practices.Unity.TestSupport.ILogger, TestSupport.Unity"  / <typeAliases >  
    < container  name ="populatedArrayWithValues" >
        < types >
          < type  type ="ILogger"  mapTo ="MockLogger"  name ="logger1" >   < lifetime  type ="singleton"   />   </ type >  
         < type  type ="ILogger"  mapTo ="SpecialLogger"  name ="logger2" >   < lifetime  type ="singleton"   />   </ type >
          < type  type ="ArrayConstructor" >  
          < typeConfig >  
            < constructor >  
              < param  name ="loggers"  parameterType ="ILoggerArray" >   < array >   < dependency  name ="logger2" />   < dependency  name ="logger1" />   </ array >   </ param >   </ constructor >   </ typeConfig >   </ type >  
  </ types >  
</ container >
  

 

  

未完待续。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值