Unity2.0学习笔记-Unity2.0基础-如何配置Unity2.0容器-设计时配置

2.2.   如何配置Unity2.0容器

配置容器包括注册类型、类型映射以及解决对象之间的依赖关系的各种所需信息。Unity可以通过XML配置文件获取配置信息,也可以通过一系列的方法调用进行运行时的容器配置(这也是我选择Unity作为我常用的IoC容器的原因,配置文件实在是太令人头痛了)。

2.2.1.   设计时配置

2.2.1.1.       开启XML智能感应

  在Visual Studio中能够通过XSD文件开启智能感应,有如下两种方法可以开启智能感应:

Visual Studio中选择XML选项卡,然后选择Schemas选项,在里面找到UnityConfiguration20.xsd文件,选择使用即可;

直接在XML配置文件中输入<unity xmlns=",然后在弹出的提示中选择http://schemas.microsoft.com/practices/2010/unity即可。

这样就能够避免在输入XML时的一些错误。

2.2.1.2.       Unity配置文件的基本结构

<?xml version="1.0" encoding="utf-8" ?>

<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">

    <alias alias="ISayHello" type="HelloWorld.ISayHello, HelloWorld" />

    <namespace name="HelloWorld" />

    <assembly name="HelloWorld" />

    <container>

      <register type="ISayHello" name="mother" mapTo="MotherSayHello" />

      <register type="ISayHello" name="child" mapTo="ChildSayHello" >

        <constructor>

          <param name="count" value="2"/>

        </constructor>

      </register>

      <instance type="ConnectionSettings" value="port=1234" typeConverter="ConnectionSettingsTypeConverter" />

      <extension type="Microsoft.Practices.Unity.Interception.InterceptionExtension, Microsoft.Practices.Unity.Interception" />

    </container>

 </unity

</configuration>

  从上面的配置文件中可以看出Unity容器配置的基本结构,在第一层可以有aliasnamespaceassemblycontainer这几种节点,它们都可以在配置文件中出现多次;然后在container节下又有registerinstanceextension三种节点,而容器的配置也主要是针对container节进行,在下面的章节中会针对这些配置节的用法进行注意解释。

2.2.1.3.       自动类型查找机制

  在大部分的框架的配置文件中,要求类型一定要写成型如:“namespace.typename,assemblyname”的类型全名。这使得的配置文件一下子变的非常臃肿,难以维护。在Unity中提供了一种名为Automatic Type Lookup的机制来解决这一问题,在之前的Hello World的例子中也已经有提到过这种机制。

Unity中使用namespaceassembly配置节来进行自动类型查找的配置。这里通过一个例子来说明自动查找的步骤,参考如下的一份配置文件:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">

    <namespace name="MyApp.Interfaces" />

    <namespace name="System" />

<assembly name="MyApp"/>

<assembly name="mscorlib, 2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

    ...

</unity>

  如果要查找ILogger接口,那么容器会按照下面的顺序进行匹配:

1.         MyApp.Interfaces.ILogger, MyApp

2.         System.ILogger, MyApp

3.         MyApp.Interfaces.ILogger, mscorlib, 2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

4.         System.ILogger, mscorlib, 2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

  即按照在配置文件中出现的先后顺序,分别对namespace.typename,assembly的各种组合进行匹配,当找到第一个匹配的项时,查找就会停止;如果找不到那么容器会抛出一个异常。

2.2.1.4.       注册类型映射

<register> 配置节是在Unity容器配置中使用最多的配置节,用来配置类型之间的映射关系,以及类型所需要的依赖注入。这个节点具有typenamemapTo三个属性,其中type属性是必填的,它表示要注册的类型(在Resolve方法中传入的类型)。name属性是可选参数,如果不填那么这个映射就是个默认类型映射,Unity容器对于默认类型映射和有名字的类型映射会区别对待,尤其是在调用ResolveAll方法时,只能获取到所有的有名字的类型映射。另外如果有多个类型映射使用同一个name那么后注册的映射关系会覆盖之前的映射关系。mapTo属性则表示了类型要映射到的实际类型,当调用Resolve方法时,会返回实际的类型。在实际使用中一般type属性中填的是一个接口或抽象的基类,然后mapTo属性中则是在运行时需要的具体类型,这样就通过依赖注入实现了解耦。

在注册一个类型映射的时候,同时还可以配置这个类型对应的Lifetime以及所需要的各种依赖关系,包括构造函数注入(Constructor)、属性注入(Property)和方法调用注入(Method)

Lifetime:这个属性用来控制实例在容器中的生命周期,默认的是TransientLifetimeManager,即每次都请求都会返回一个新的实例;比较常用的是ContainerControlledLifetimeManager,每次请求都会返回同一个实例,即我们平常所说的单例模式。在Unity中内置了很多种在开发过程中可能会用到的管理器,有兴趣的同学可以查看对应的MSDN帮助,除此之外开发者还能够按照自己的需要开发自己的LifetimeManager来满足不同的需求。配置的样例如下:

<register type="ILogger" mapTo="SerialPortLogger">

 <!-- Simple use of lifetime - singleton instance -->

 <lifetime type="singleton" />

</register>

<register type="TypeWithCustomLifetime">

 <!-- Use a Lifetime manager instance created by a type converter.

Type converter gets passed extra information provided in

in value attribute -->

 <lifetime type="SessionLifetimeManager"

            value="Session#1" typeConverter="SessionLifetimeConverter" />

</register>

Constructor:这个属性用来在实例的构造期间进行构造函数注入,Unity容器在创建实例时默认会使用参数列表最长的构造函数,而使用这个属性则可以改变容器的默认行为,而且可以对构造函数中的各个参数的值进行指定。在之前的HelloWorld示例中已经使用过了构造函数注入,当时的配置如下:

<register type="ISayHello" name="child" mapTo="ChildSayHello" >

 <constructor>

    <param name="count" value="2"/>

 </constructor>

</register>

其中param表示构造函数的参数,可以重复多个,里面使用namevalue属性来制定参数的名字和值,这里就是调用参数名为count,类型为Int型的构造函数;当然你也可以使用type属性来指定参数的具体类型,使用dependencyName属性来指定参数注入所要用到的依赖的名字(就是它在register节点中注册时的name),使用dependencyType属性来指定参数注入所要用到的依赖类型,如果设置了这个属性而不设置dependencyName属性,那么容器会去查找这个类型的默认实例进行注入,否则使用指定的实例。

Property:这个属性用来对实例的属性进行注入,可以有一个或多个配置,具体的配置内容与构造函数中的param类同,需要注意的是,如果在配置中只指明要注入的属性的name,那么容器会根据该属性类型在容器中的默认映射关系进行注入,配置样例如下:

<register type="ILogger" mapTo="SerialPortLogger">

 <property name="Settings" dependencyType="PortSettings" dependencyName="highSpeedSettings" />

</register>

Method:这个属性用来在实例创建后调用指定的方法,并按照配置对该方法的参数进行注入,配置的方法跟constructor属性完全相同,只是将constructor替换成method并加上对应方法的name即可,配置样例如下:

<register type="MyLogger">

 <method name="Initialize">

    <param name="loggerSettings" />

 </method>

</register>

2.2.1.5.       注册类型实例

<instance>节用来向容器中注册一个不是通过容器创建的类型实例,它可以是一个简单的字符串表示,也可以是一个复杂的字符串,然后通过一个typeConverter进行转换。这个配置节包括nametypevaluetypeConverter四个属性,其中type属性的默认值为System. String,如果需要进行自定义的类型转换,那么只要对typeConverter赋上相应的值即可。

Tip:因为实例的创建并不是通过容器进行的,所以无法在此配置各种依赖注入。

 

2.2.1.6. 读取配置创建Unity容器

通过上面的章节,已经能够对Unity容器的配置有了主观的了解,接下来要做的就是把配置文件跟具体的Unity容器关联在一起,映射到代码中只有一行,如下:

IUnityContainer container = new UnityContainer().LoadConfiguration();

TipLoadConfigurationMicrosoft.Practices.Unity.Configuration;名字空间下的扩展方法,在使用前请不要忘了添加对应的名字空间引用。

posted on 2011-04-05 16:40  yingql  阅读(3132)  评论(2编辑  收藏  举报

导航