上一章中,我使用Unity重構了解決方案。不過在Application工程中仍然需要引用其他各個依懶項。很明顯,這樣做並不能實現計算器模塊的可插拔。今天,將以此為目標,對該解決方案進行再次的重構。
首先,在使用Prism框架加載的程序集中分別添加一個類,並讓這些類實現IModule接口。當Prism框架加載某個程序集后,將首先在程序集中搜索實現了該接口的類。之后將會調用該接口的Initialize方法。於是,我們可以在這個方法中實現程序集內部的初化始操作,或者執行某個動作。通過這種機制,可以實現程序集的完全解藕。具體的操作如下:
1. 在CalculatorLibrary 程序集中添加一個類:CalculatorModule,並讓其實現IModule接口。代碼如下:
3 {
4 public CalculatorModule(IUnityContainer container)
5 {
6 this.container = container;
7 }
8 void IModule.Initialize()
9 {
10 container.RegisterType<ICalculator, Calculator>();
11 container.RegisterType<ICalculatorReplLoop, CalculatorReplLoop>();
12 }
13
14 IUnityContainer container;
15 }
2. 在InputOutputLibrary 程序集中添加一個類:InputOutputModule,並讓其實現IModule接口。代碼如下:
3 {
4 public InputOutputModule(IUnityContainer container)
5 {
6 this.container = container;
7 }
8 void IModule.Initialize()
9 {
10 container.RegisterType<IInputService, ConsoleInputService>();
11 container.RegisterType<IOutputService, ConsoleOutputService>( " OutputService1 ");
12 container.RegisterType<IOutputService, MsgBoxOutputService>( " OutputService2 ");
13 }
14
15 IUnityContainer container;
16 }
3. 在CommandParserLibrary 程序集中添加一個類:InputOutputModule,並讓其實現IModule接口。代碼如下:
3 {
4 public InputParsingModule(IUnityContainer container)
5 {
6 this.container = container;
7 }
8 void IModule.Initialize()
9 {
10 container.RegisterType<IInputParserService, InputParserService>();
11 }
12
13 IUnityContainer container;
14 }
4. 在解決方案中新建一個類庫:MainModuleLibrary,在其中添加一個類:MainModule,並實現IModule接口。這個類庫將會作為計算器模塊的入口,在該類的Initialize方法中將會啟動計算器。代碼如下:
3 {
4 public MainModule(IServiceLocator serviceLocator)
5 {
6 this.serviceLocator = serviceLocator;
7 }
8 void IModule.Initialize()
9 {
10 ICalculatorReplLoop loop =
11 serviceLocator.GetInstance<ICalculatorReplLoop>();
12
13 loop.Run();
14 }
15
16 IServiceLocator serviceLocator;
17 }
到此,程序集部分的代碼全部完成。可以看到,前三個程序集中Module類,使用Initialize方法將各個類注冊到了Container對象中,由Prism框架進行管理。我們可以在需要的時候,在任何地方通過Prism框架將其取得調用;第四個程序集作為計算器的入口,在Module類的Initialize方法中啟動計算器。這里的代碼在上一章中基本都用過,在此不再描述。
經過上面的修改,我們可以非常方便的對其進行調用,並且不需要任何的引用,實現了完全的解藕。下面的代碼,將指示我們如何在主程序中啟動這些程序集。如下:
3 {
4 UnityContainer Container = new UnityContainer();
5
6 Container.RegisterInstance<IServiceLocator>(
7 new UnityServiceLocatorAdapter(Container));
8
9 Container.RegisterType<IModuleInitializer, ModuleInitializer>();
10
11 ILoggerFacade logger = new TextLogger();
12 Container.RegisterInstance<ILoggerFacade>(logger);
13
14 Container.RegisterType<IModuleCatalog, ConfigurationModuleCatalog>();
15
16 Container.RegisterType<IModuleManager, ModuleManager>();
17
18 IModuleManager Manager = Container.Resolve<IModuleManager>();
19 Manager.Run();
20 }
上面的代碼中,ModuleInitializer TextLogger, ModuleCatalog 三個類,都是ModuleManager的構造函數中所需要的。如果不注冊,程序將會出錯。在當前框架中,實現了ILoggerFacade接口的類有多個。直接使用RegisterType來注冊,也將會報錯,我沒有看源代碼,不知道他的名稱是什么,所以在此直接使用實體注冊,這也可以實現同樣的效果。
在程序啟動運行時,Prism框架會去系統的配置文件中加獲取模塊的信息,並加它們加載到系統中。這些配置跟上一章中的類的配置不一樣,具體請參考下面的xml文件:
3 < configuration >
4 < configSections >
5 < section name ="modules"
6 type ="Microsoft.Practices.Prism.Modularity.ModulesConfigurationSection, Microsoft.Practices.Prism" />
7 </ configSections >
8 < modules >
9 < module assemblyFile ="CommandParserLibrary.dll"
10 moduleType ="CommandParserLibrary.InputParsingModule, CommandParserLibrary"
11 moduleName ="Parsing" />
12 < module assemblyFile ="CalculatorLibrary.dll"
13 moduleType ="CalculatorLibrary.CalculatorModule, CalculatorLibrary"
14 moduleName ="Calculator" />
15 < module assemblyFile ="InputOutputLibrary.dll"
16 moduleType ="InputOutputLibrary.InputOutputModule, InputOutputLibrary"
17 moduleName ="InputOutput" />
18 < module assemblyFile ="MainModuleLibrary.dll"
19 moduleType ="MainModuleLibrary.MainModule, MainModuleLibrary"
20 moduleName ="Main" >
21 < dependencies >
22 < dependency moduleName ="Parsing" />
23 < dependency moduleName ="Calculator" />
24 < dependency moduleName ="InputOutput" />
25 </ dependencies >
26 </ module >
27 </ modules >
28 </ configuration >
到此,計算器模塊的完全解藕順利完成。我們可以刪掉Application中對計算器模塊的所有引用。將其它模塊編譯好后,拷到Application項目的Debug目錄下試一下。這個項目,只是Prism框架的一個簡單應用。在后續的章節中,我將繼續深入研究對該框架的使用。歡迎大家一起來學習Prism框架,共同進步。請大家多多指教。
在此,奉上該解決方案的源碼:請點擊 這里 下載。