Enterprise Library - Unity Application Block 学习手册(最新版) Part 2

本文演示Enterprise Library – Unity Application Block依赖注入模块的使用。本文练习配置container在运行时执行依赖注入,不需依赖于在类代码中做attributes标识和设置生命周期管理器。本文由 http://blog.entlib.com 开源ASP.NET博客平台小组根据EntLib HOL手册编译提供,欢迎交流。
 
练习二:通过配置使用Container 容器
首先,打开Labs\Lab02\begin\StocksTicker 目录下的StockTicker.sln Solution项目文件。
 
为了提供依赖注入的配置,调用container的RegisterType方法将接收InjectionMember对象,InjectionMember是一个基类,继承类有InjectionProperty和InjectionConstructor,在下面会用到。
 
1. 更新container配置,重载默认的注入规则
(1)更新IStockQuoteService接口调用RegisterType方法的代码,使用InjectionProperty对象注入Logger属性,代码如下所示。
            using (IUnityContainer container = new UnityContainer())
            {
                container
                    .RegisterType<IStocksTickerView, StocksTickerForm>()
                    .RegisterType<IStockQuoteService, MoneyCentralStockQuoteService>(
                        new InjectionProperty("Logger"))
                    .RegisterType<ILogger, ConsoleLogger>()
                    .RegisterType<ILogger, TraceSourceLogger>("UI")
                    .RegisterInstance(new TraceSource("UI", SourceLevels.All));
 
                StocksTickerPresenter presenter
                    = container.Resolve<StocksTickerPresenter>();
 
                Application.Run((Form)presenter.View);
            }
 
上述代码中配置的InjectionProperty对象表示名称为Logger的属性将被注入container。因为针对该属性没有进一步的配置,因此在获取注入该属性值时,解析该属性的类型ILogger。这和前一节Dependency attribute的使用一样。
 
(2)使用RegisterType方法设置StocksTickerPresenter类的注入,代码如下所示。
            using (IUnityContainer container = new UnityContainer())
            {
                container
                    .RegisterType<IStocksTickerView, StocksTickerForm>()
                    .RegisterType<IStockQuoteService, MoneyCentralStockQuoteService>(
                        new InjectionProperty("Logger"))
                    .RegisterType<ILogger, ConsoleLogger>()
                    .RegisterType<ILogger, TraceSourceLogger>("UI")
                    .RegisterInstance(new TraceSource("UI", SourceLevels.All))
                    .RegisterType<StocksTickerPresenter>(
                        new InjectionProperty("Logger", new ResolvedParameter<ILogger>("UI"))) ;
 
                StocksTickerPresenter presenter
                    = container.Resolve<StocksTickerPresenter>();
 
                Application.Run((Form)presenter.View);
            }
 
上述代码中,RegisterType方法没有用来操作类型映射,而仅仅用来注入Logger属性,正因为如此,仅有一个泛型类型的参数。此外,InjectionProperty还传入一个ResolvedParameter对象,该参数表示解析的对象实例名称(前面的示例代码不需要,因此省略了)。
 
这些配置已经足够成功运行范例程序了。InjectionConstructor attribute 触发TraceSourceLogger对象的创建,并注入到已注册的TraceSource实例。然而,在很多情况下,你不能够应用InjectionConstructor attribute或者你希望重载attribute和注入不同的对象。下一步,介绍如何使用RegisterType方法重载默认对象创建规则,使用不同的构造器来创建TraceSourceLogger 对象。
 
(3)更新ILogger 接口的RegisterType调用方法,使用UI名称来注入对仅含有有一个字符串参数的构造器调用,代码如下所示。
            using (IUnityContainer container = new UnityContainer())
            {
                container
                    .RegisterType<IStocksTickerView, StocksTickerForm>()
                    .RegisterType<IStockQuoteService, MoneyCentralStockQuoteService>(
                        new InjectionProperty("Logger"))
                    .RegisterType<ILogger, ConsoleLogger>()
                    .RegisterType<ILogger, TraceSourceLogger>("UI",
new InjectionConstructor("UI"))
                    .RegisterInstance(new TraceSource("UI", SourceLevels.All))
                    .RegisterType<StocksTickerPresenter>(
                        new InjectionProperty("Logger", new ResolvedParameter<ILogger>("UI")));
 
                StocksTickerPresenter presenter
                    = container.Resolve<StocksTickerPresenter>();
 
                Application.Run((Form)presenter.View);
            }
 
InjectionConstructor 表明根据参数来决定调用哪一个构造函数。上述代码中,传入 UI 字符串,将调用仅仅有一个字符串参数的构造函数,并传入 UI 作为其参数,代替标识有InjectionConstructor attribute的构造函数。
 
删除对RegisterInstance的调用,因为这段代码已经没有必要了。
.RegisterInstance(new TraceSource("UI", SourceLevels.All)
 
2. 运行范例程序
现在运行范例程序,应该和之前的运行效果一样,但是现在不需要在源代码中添加一些额外的attributes。除了在TraceSourceLogger类的构造函数中还保留了InjectionConstructor attribute,其目的是说明了如何使用配置来覆盖attribute的标识。
 
使用RegisterType方法配置注入提供了一定的灵活性,这是使用attributes所没有的,然而,它也需要为container指定每一个注入。
 
3. 使用生命周期管理器(Lifetime manager)
Container使用lifetime manager有2个目的:
(1)在特定的上下文,确保解析一个特定的对象时总是返回相同的实例。
(2)合理释放解析的对象。
下面的练习中,内置的ContainerControlledLifetimeManager将用来释放TraceSourceLogger对象。
 
更新TraceSourceLogger 类实现IDisposable 接口
目前实现的TraceSourceLogger类在每一个消息记录日志后,都需要调用flush方法,并且不会关闭。在本练习中,该类将更新为实现IDisposable接口,正确关闭TraceSource。
(1)打开Loggers\TraceSourceLogger.cs文件
(2)添加TraceSourceLogger类实现IDisposable接口,如下所示。
(3)删除Log方法中调用Flush方法的代码。
public void Log(string message, TraceEventType eventType)
{
    this.traceSource.TraceEvent(eventType, 0, message);
    // this.traceSource.Flush(); --- 删除这行代码
}
(4)添加实现IDisposable接口的Dispose方法,代码如下所示。
        public void Dispose()
        {
            if (this.traceSource != null)
            {
                this.traceSource.TraceInformation("Shutting down logger");
                this.traceSource.Close();
                this.traceSource = null;
            }
        }
上述代码记录shutting down消息,然后关闭trace source对象。
 
更新container 对TraceSourceLogger 类配置调用,使用Lifetime manager
更新对UI - ILogger接口的RegisterType调用方法,传入一个新的ContainerControlledLifetimeManager对象,代码如下所示。
            using (IUnityContainer container = new UnityContainer())
            {
                container
                    .RegisterType<IStocksTickerView, StocksTickerForm>()
                    .RegisterType<IStockQuoteService, MoneyCentralStockQuoteService>(
                        new InjectionProperty("Logger"))
                    .RegisterType<ILogger, ConsoleLogger>()
                    .RegisterType<ILogger, TraceSourceLogger>(
                        "UI",
                        new ContainerControlledLifetimeManager(),
                        new InjectionConstructor("UI"))
                    .RegisterType<StocksTickerPresenter>(
                        new InjectionProperty("Logger", new ResolvedParameter<ILogger>("UI")));
 
                StocksTickerPresenter presenter
                    = container.Resolve<StocksTickerPresenter>();
 
                Application.Run((Form)presenter.View);
            }
 
lifetime manager是RegisterType方法的一个可选参数。
 
再次运行范例程序,按照前面的操作,输入GM/MSFT等等股票代码,最后关闭主窗口。接着,我们打开ui.log文件(在StocksTicker\bin\Debug目录),会发现在该文件的最后两行,有类似如下的记录。
UI Information: 0 : Shutting down logger
    DateTime=2009-02-11T19:02:07.8990000ZZ
 
http://www.entlib.com专业ASP.NET电子商务平台小组,欢迎你继续访问Unity Application Block学习手册。
 
参考文档:
Unity Application Block Hands-On Labs for Enterprise Library

你可能感兴趣的:(application)