Lab 1: Using a Unity Container
Estimated time to complete this lab: 15 minutes
估計完成時間:15分鐘
Introduction
In this lab, you will PRactice using a Unity container to create application objects and wire them together. You will update a simple stocks ticker application to replace calls to constructors and property setters with requests to a properly configured Unity container.
在這個實驗中,你將練習(xí)使用一個Unity容起來創(chuàng)建應(yīng)用對象并將他們連貫在一起。你將更新一個簡單的股票收錄機應(yīng)用,替換對構(gòu)造函數(shù)的調(diào)用和屬性的設(shè)置器,這需要恰當(dāng)?shù)呐渲肬nity容器。
To begin this lab, open the StocksTicker.sln file located in the /Lab01/begin/StocksTicker folder.
要開始這個實驗,打開位于/Lab01/begin/StocksTicker 文件夾下的StocksTicker.sln文件。
Running the Application
Start by launching the application. To launch the application, on the Visual Studio Debug menu click Start Without Debugging or press Ctrl-F5. This opens a form and a console window. The console window opens to display the messages logged to the console while the application runs.
通過啟動應(yīng)用來開始。要運行應(yīng)用,打開VS的調(diào)試菜單,單擊菜單項 開始執(zhí)行(不調(diào)試),或按下Ctrl-F5。這樣就會打開一個Form窗體和一個控制臺窗口。在應(yīng)用運行期間控制臺窗口會一直打開,并顯示日志消息到控制臺。
On the application form, you can enter stock quote symbols, consisting of only letters, and subscribe to them by clicking the Subscribe button. When the Refresh check box is selected, the form displays the latest information about each of the subscribed stock symbols. The form will Flash each time an update for a stock symbol is received. The following figure illustrates a sample stocks ticker application.
在應(yīng)用的Form窗體中,你可以輸入股票報價符號,僅由字母組成,然后通過單擊 訂閱(subscribe) 按鈕訂閱他們。當(dāng)刷新(Refresh)復(fù)選框被選中,窗體將會顯示每個股票的最新信息。窗體每收到一個股票的更新信息就會刷新顯示。下圖示例了一個簡單的股票收錄機應(yīng)用。



By default, the console is used to log information about the retrieval of updated quotes. The ui.log file (located in the StocksTicker/bin/Debug folder) contains information about the Operations performed by the user interface (UI). After you close the application, you can review the contents of the log file.
在默認(rèn)情況下,控制臺用來顯示接收到的更新的信息。而ui.log文件(位于StocksTicker/bin/Debug文件夾)包含關(guān)于在UI的的操作的記錄。在你關(guān)閉應(yīng)用之后,你可以重新查看日志文件里的內(nèi)容。
Reviewing the Application
The application is built by using the Model-View-Presenter (MVP) pattern. For information about the MVP pattern, see Separated Presentation on MSDN. The following figureError! Reference source not found. shows the classes involved in the application and their relationships.
這個應(yīng)用使用了MVP模式來創(chuàng)建。關(guān)于MVP模式,可以見MSDN上的Separated Presentation。下圖展示了應(yīng)用涉及到的類和他們之間的關(guān)系。

The StocksTickerForm class implements the user interface, and the IStockQuoteService interface defines a service for retrieving current stock quotes, the RandomStockQuoteService is the concrete implementation of IStockQuoteService that is used in these labs. The ILogger interface and its implementations are used to log messages about the operation of the application. Finally, the StocksTickerPresenter class plays the presenter role.
StocksTickerForm類實現(xiàn)了UI,IStockQuoteService接口定義了一個獲取當(dāng)前股票符號的服務(wù),在本實驗中使用的RandomStockQuoteService類具體實現(xiàn)了IStockQuoteService接口。ILogger接口和他的實現(xiàn)類被用來記錄關(guān)于應(yīng)用的操作的日志消息。最后,StocksTickerPresenter扮演了presenter的角色。
All classes in the solution, including the presenter class, have constructors that take all of the required collaborators as parameters and properties where optional collaborators can be set. In the presenter's case, the required collaborators are its view and the service used to poll for updates, and logger is an optional collaborator.
解決方案中的所有類,包括presenter類,都有構(gòu)造函數(shù),包含了所有必需的構(gòu)造信息作為參數(shù),可選的構(gòu)造者作為屬性也是可以設(shè)置的。在presenter的情況下,必需的構(gòu)造者是他的view和用來得到更新的服務(wù),而日志器是可選構(gòu)造者。
The static Program.Main() method creates all the involved objects in order and connects them together before launching the user interface (UI). The purpose of this lab is to replace the explicit creation of these objects with the use of a Unity container.
靜態(tài)的Program.Main()方法創(chuàng)建了所有需要涉及的對象并在啟動UI之前將它們連接在一起。這個實驗的目的是通過對一個Unity 容器的使用來替換這些對象的顯式創(chuàng)建。
Task 1: Using a Container
In this task, the application's startup code will be updated to use a Unity container to create and connect the application's objects. This will replace the use of explicit calls to the classes' constructors and property setters.
在這個任務(wù)中,應(yīng)用的啟動代碼將會被更新,使用一個Unity容器來創(chuàng)建和連接應(yīng)用的對象。這將會替換對顯式調(diào)用類的構(gòu)造函數(shù)和屬性的設(shè)置器的使用。
Adding References to the Required Assemblies

Update the Startup Code to Use a Container
To update the startup code to use a container
要更新啟動代碼來使用一個容器
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity;

Unity containers implement the IDisposable interface. This enables the new code to take advantage of the using statement to dispose the new container. Lab 2 elaborates on the result of disposing a container.
Unity容器實現(xiàn)了IDisposable接口。這就允許新的代碼使用using語法的優(yōu)勢來銷毀創(chuàng)建的容器。實驗2詳細(xì)說明了銷毀一個容器的過程和結(jié)果。


Although the container requires additional configuration to resolve the requested presenter, the messages for the ResolutionFailedException and its chain of InnerExceptions reveal some interesting details:
盡管容器需要進一步配置來確定需要的presenter,異常ResolutionFailedException和他的InnerExceptions消息揭示了一些有趣的細(xì)節(jié):
For information about Unity's autowiring rules, see the topic "Annotating Objects for Constructor Injection" in the Unity 3 documentation.
關(guān)于Unity的autowiring規(guī)則的信息,請看Unity 3 文檔的Annotating Objects for Constructor Injection主題。

Using the RegisterType method is primarily how you will set up a container. In addition to mapping abstract types to concrete ones as described in this step, you can use the RegisterType method to override the default injection rules and specify lifetime managers. The next exercises will show additional uses of the RegisterType method. For details about mapping types see the topic "Registering Types and Type Mappings" in the Unity 3 documentation.
使用RegisterType方法是你設(shè)置一個容器主要的內(nèi)容。在這個步驟中描述了映射抽象類型到具體的類型,除此之位,你可以使用RegisterType方法來重載默認(rèn)的注入規(guī)則和明確指定生命周期管理器。在下一個練習(xí)中將會展示RegisterType方法的額外用法。關(guān)于映射類型的更多詳細(xì)信息,請柬Unity 3 文檔的Registering Types and Type Mappings主題。


Running the Application
Launch the application and use it. The application behaves as it did before the changes, except that no logging will be available in the console or the ui.log file.
運行應(yīng)用并使用它。這個應(yīng)用表現(xiàn)的跟修改前一樣,除了沒有日志信息出現(xiàn)在控制臺窗口中和ui.log文件中。
Task 2: Using Attributes to Control Injection
Attributes can be used to override the default injection rules. In some cases, attributes are used to opt-in for injection on members ignored by the default rules. In other cases, attributes must be used to override the default rules or disambiguate cases where the rules cannot be used.
特性可以用來重載默認(rèn)的注入規(guī)則。在某些情況下,特性被用來為成員選擇注入,以忽略默認(rèn)規(guī)則。在另一些情況下,特性必須用來重載默認(rèn)規(guī)則,或在不能使用規(guī)則的情況下消除歧義。
Using Attributes to Enable Property Injection
It is very common to have the container set properties, in addition to passing in dependencies by using constructor arguments.
在通過構(gòu)造函數(shù)參數(shù)來傳遞依賴項的方法之外,使用容器來設(shè)置屬性也是非常通用的。
To set up injection for the Logger property on the RandomStockQuoteService class
在RandomStockQuoteService類為logger屬性設(shè)置注入
using Microsoft.Practices.Unity;



Adding a Type Registration to Resolve the ILogger Interface
Because the container must now resolve the ILogger interface, a mapping from the interface to a concrete type must be added to the container. In this example, the interface will be mapped to the ConsoleLogger class in order to match the code originally used to wire-up the objects.
因為容器現(xiàn)在必需確定ILogger接口,一個指向接口的確定類型映射必需添加到容器中。在這個示例中,這個接口將被映射到ConsoleLogger類,以匹配原來的連接對象的代碼。
To add a type registration to resolve the ILogger interface
添加一個類型注冊器來確定ILogger接口



Running the Application
Launch and use the application. Operations performed by the service are logged to the console, but UI operations are not logged to the console because the Logger property on the presenter class is still not injected.
運行并使用應(yīng)用。服務(wù)的操作被記錄到控制臺,但是UI的操作沒有被記錄到控制臺因為presenter里面的Logger屬性還沒有設(shè)置注入。
Setting Up Injection for the Logger Property on the StocksTickerPresenter Class
To inject the Logger property on the presenter class, this lab uses the same Dependency attribute. However, because a different logger instance is to be injected, you need a way to differentiate the loggers. The Unity container lets you register the same type multiple times, and give each registration a different name. When that dependency is resolved, the name can be used to specify exactly which instance you want. In this lab, you will use different names so that you can tell the difference between the logger objects.
要在presenter類上注入Logger屬性,這個實驗使用的是相同的Dependency特性。但是,因為不同的logger實例要被注入,你需要一種方式來區(qū)分Loggers。Unity容器允許你注冊同一個類型多次,并給每個注冊設(shè)置不同的名字。當(dāng)依賴項被確定的時候,名稱可以用來精確的指定哪個實例是你需要的。在這個實驗中,你將使用不同的名字這樣你就可以說明兩個logger對象的不同了。
To set up injection for the Logger property on the StocksTickerPresenter class
在StocksTickerPresenter類上設(shè)置Logger屬性的注入
using Microsoft.Practices.Unity;

Adding a Type Registration to Resolve the ILogger Interface with the "UI" Name
To add a type registration to resolve the ILogger interface with the "UI" name
使用"UI"這個名字來添加一個類型注冊,以確定ILogger接口



Debugging the Application
Launch the application. The debugger should break with an unhandled exception that indicates a new failure while trying to resolve the Logger property on the presenter to an instance of TraceSourceLogger. Examining the chain of InnerExceptions shows that the root cause of the failure is indicated with an InvalidOperationException and the message "The type TraceSourceLogger has multiple constructors of length 1. Unable to disambiguate." In this case, Unity's default injection rules cannot determine how to build the instance, so the container must be explicitly configured to build it.
運行應(yīng)用。調(diào)試器將會被一個未處理的異常中斷,其指示了在嘗試確定presenter的Logger屬性為TraceSourceLogger實例的時候產(chǎn)生了一個新的錯誤。仔細(xì)檢查異常鏈中的InnerExceptions展示了導(dǎo)致這個錯誤的根本原因是一個InvalidOperationException異常,其消息是"The type TraceSourceLogger has multiple constructors of length 1. Unable to disambiguate."在這個情況下,Unity的默認(rèn)注入規(guī)則不能確定如何創(chuàng)建實例,所以容器必需明確的配置如何構(gòu)建他。
Indicating Which Constructor to Use When Building an Instance of TraceSourceLogger with the InjectionConstructor Attribute
This lab uses an attribute to indicate which of the two available constructors should be used to create an instance of the TraceSourceLogger class.
這個實驗使用一個特性來指示已有的兩個構(gòu)造函數(shù)中的哪個來創(chuàng)建TraceSourceLogger類的實例。
To indicate which constructor to use when building an instance of TraceSourceLogger with the InjectionConstructor attribute
用注入構(gòu)造函數(shù)特性來指定當(dāng)創(chuàng)建一個TraceSourceLogger實例使用哪個構(gòu)造函數(shù)
using Microsoft.Practices.Unity;

Adding an Instance Registration to Resolve the TraceSource Type
After being pointed to one of the constructors, Unity's default injection rules take effect and an instance of the .NET Framework TraceSource class will be resolved to be used as the argument for the constructor call. Instead of instructing the container about how to build such an instance, which would be problematic since the class cannot be annotated with attributes, a pre-built instance will be supplied to the container.
在指定了一個構(gòu)造函數(shù)之后,Unity的默認(rèn)注入規(guī)則將起作用并且一個.NET Framework TraceSource類的實例將會被確認(rèn)用來作為調(diào)用個構(gòu)造函數(shù)時的參數(shù)。不是告訴容器如何創(chuàng)建一個這樣的實例,因為這樣可能會有問題如果這個類不能通過特性注釋,取而代之的是,直接預(yù)先建立一個實例并提供給容器。(這里翻譯我自己都覺得奇怪,我也沒看懂)。
To add an instance registration to resolve the TraceSource type
添加一個實例注冊器來確定的TraceSource類型



Running the Application
Launch and use the application. Now the application should work exactly as it did initially, with messages from the UI being logged to the ui.log file (located in the StocksTicker/bin/Debug folder) and messages from the service being logged to the console.
運行并使用這個應(yīng)用。現(xiàn)在這個應(yīng)用應(yīng)該能夠像最初那樣正確的工作了,來自UI的消息將被記錄到ui.log文件中(位于StocksTicker/bin/Debug文件夾)而來自服務(wù)的消息將會被記錄到控制臺。
Attributes are a convenient mechanism to override or disambiguate the container's default injection rules but can result in brittle dependencies. Using names can make particularly brittle dependencies because they get hard-coded in the source code. The next labs show alternative mechanisms to externalize the setup of a container without involving the objects being created. To verify you have completed the lab correctly, you can use the solution provided in the /Lab01/end/StocksTicker folder.
特性是一個方便的機制來重載或消除容器的默認(rèn)注入規(guī)則但是可能導(dǎo)致零碎的依賴關(guān)系。使用名稱將導(dǎo)致特別零碎的依賴因為他們使用硬編碼方式存在源代碼里面。在下一個實驗中將展示臺體的機制來具體化一個容器的安裝避免涉及到對象的創(chuàng)建。你可以使用/Lab01/end/StocksTicker文件夾下提供的解決方案來來驗證你完成的實驗是否正確。
新聞熱點
疑難解答