本文演示Enterprise Library – Unity Application Block依赖注入模块的使用。本文练习通过应用程序的配置文件来设置Unity container,通过配置文件设置依赖注入和Part 2使用API配置比较相似。事实上,配置设置可以认为是调用API的脚本。使用Unity,最基本步骤有三步:1. 建立容器;2. 将接口与类的映射注册到容器中;3. 从容器中解析出正确的对象。
本文由http://blog.entlib.com 开源ASP.NET博客平台小组根据EntLib HOL手册编译提供,欢迎交流。
练习三:使用配置文件来设置依赖注入容器(Container)
首先,打开Labs\Lab03\begin\StocksTicker 目录下StocksTicker.sln文件。添加对Microsoft.Practices.Unity.Configuration 和 System.Configuration程序集的引用。.NET Framework内置的System.Configuration程序集用来从应用程序配置文件检索配置信息。
1. 更新启动代码,使用配置文件来设置container
(1)打开program.cs文件,添加对如下命名空间的引用。
using System.Configuration;
using Microsoft.Practices.Unity.Configuration;
(2)从配置文件中检索Unity 配置节,用来配置container,代替对RegisterType方法的调用,代码如下所示。
using (IUnityContainer container = new UnityContainer())
{
UnityConfigurationSection config
= (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
if (config != null)
{
config.Containers.Default.Configure(container);
}
StocksTickerPresenter presenter
= container.Resolve<StocksTickerPresenter>();
Application.Run((Form)presenter.View);
}
ConfigurationManager 用来从配置文件中检索配置信息。上述代码使用unity参数从配置文件中获得UnityConfigurationSection对象,表示默认的container配置。
2. 更新配置文件包含Container配置信息
打开app.config文件,在 Visual Studio 编辑器中,添加如下unity 配置节点。(EntLib.com 开源小组主:比较遗憾的是,目前EntLib 附带的编辑器不支持对unity application block的相关属性及配置项进行编辑,因此需要手动编辑配置文件)。
<configSections>
...
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
其中,section的名称unity只有和前面的代码中指定的名称一致即可。
继续添加unity节点元素,如下所示。
</system.diagnostics>
<unity>
</unity>
</configuration>
节点元素名称必须和前面在configSections中注册的section名称保持一致。
然后为练习中使用到的类型添加typeAlias元素,如下所示:
<unity>
<typeAliases>
<typeAlias
alias="string"
type="System.String, mscorlib" />
<typeAlias
alias="TraceSource"
type="System.Diagnostics.TraceSource, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<typeAlias
alias="singleton"
type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<typeAlias
alias="ILogger"
type="StocksTicker.Loggers.ILogger, StocksTicker" />
<typeAlias
alias="ConsoleLogger"
type="StocksTicker.Loggers.ConsoleLogger, StocksTicker" />
<typeAlias
alias="TraceSourceLogger"
type="StocksTicker.Loggers.TraceSourceLogger, StocksTicker" />
<typeAlias
alias="IStockQuoteService"
type="StocksTicker.StockQuoteServices.IStockQuoteService, StocksTicker" />
<typeAlias
alias="MoneyCentralStockQuoteService"
type="StocksTicker.StockQuoteServices.MoneyCentralStockQuoteService, StocksTicker" />
<typeAlias
alias="IStocksTickerView"
type="StocksTicker.UI.IStocksTickerView, StocksTicker" />
<typeAlias
alias="StocksTickerForm"
type="StocksTicker.UI.StocksTickerForm, StocksTicker" />
<typeAlias
alias="StocksTickerPresenter"
type="StocksTicker.UI.StocksTickerPresenter, StocksTicker" />
</typeAliases>
</unity>
虽然类型别名(type aliases)不是必须的,但这样使得配置文件更易于阅读。每一个typeAlias元素都包含一个alias,在Unity 配置项中可用来代替具体的类型名称。
在配置文件中,继续添加containers和container元素,如下所示。
</typeAliases>
<containers>
<container>
</container>
</containers>
</unity>
默认的container容器和其他命名的container没有什么不同,除了比较容易地通过配置管理对象的Default 属性获取到配置信息。
为默认的cotainer添加types元素。
<containers>
<container>
<types>
</types>
</container>
</containers>
types元素的子节点类似于对RegisterType方法的调用,用来将类型注册到容器中。
下面添加type元素,将IStocksTickerView接口映射到StocksTickerForm类:
<types>
<type type="IStocksTickerView" mapTo="StocksTickerForm"/>
</types>
注:上面使用了类型名称的别名,实际的类型名称也可以在这里使用。
继续添加type元素,映射IStockQuoteService接口到MoneyCentralStockQuoteService类,且子元素typeConfig 配置注入Logger属性。
<types>
<type type="IStocksTickerView" mapTo="StocksTickerForm"/>
<type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
<typeConfig>
<property name="Logger" propertyType="ILogger"/>
</typeConfig>
</type>
</types>
添加添加type元素,映射ILogger接口到ConsoleLogger类:
<types>
<type type="IStocksTickerView" mapTo="StocksTickerForm"/>
<type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
<typeConfig>
<property name="Logger" propertyType="ILogger"/>
</typeConfig>
</type>
<type type="ILogger" mapTo="ConsoleLogger"/>
</types>
下面稍有点复杂,添加type元素映射ILogger接口到TraceSourceLogger类,命名为UI。并带有一个子元素typeConfig 表示使用单一字符串参数的构造函数来创建对象实例,定义value元素,传入UI字符串参数。另外,子元素lifetime 通过singleton别名表示使用ContainerControlledLifetimeManager。
<types>
<type type="IStocksTickerView" mapTo="StocksTickerForm"/>
<type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
...
</type>
<type type="ILogger" mapTo="ConsoleLogger"/>
<type name="UI" type="ILogger" mapTo="TraceSourceLogger">
<lifetime type="singleton"/>
<typeConfig>
<constructor>
<param name="sourceName" parameterType="string">
<value value="UI"/>
</param>
</constructor>
</typeConfig>
</type>
</types>
constructor元素和代码中的InjectionConstructor类一样。
最后添加为StocksTickerPresenter类添加type元素,并包括一个子元素typeConfig,配置注入Logger属性,且注入的关键字包括ILogger接口以及名称UI(使用dependency 元素指定名称为UI)。
<types>
<type type="IStocksTickerView" mapTo="StocksTickerForm"/>
<type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
...
</type>
<type type="ILogger" mapTo="ConsoleLogger"/>
<type name="UI" type="ILogger" mapTo="TraceSourceLogger">
...
</type>
<type type="StocksTickerPresenter">
<typeConfig>
<property name="Logger" propertyType="ILogger">
<dependency name="UI"/>
</property>
</typeConfig>
</type>
</types>
下图是Unity配置项的Schema图,还包括每个元素可以设置的属性。
现在运行范例程序,其运行效果和前面的Part 1 – 2 一致,包括日志功能。
http://www.entlib.com专业ASP.NET电子商务平台小组,欢迎你继续访问Unity Application Block学习手册。
参考文档:
Unity Application Block Hands-On Labs for Enterprise Library