Prism学习(3)---实现可插拔的模块

时间:2022-06-16 02:48:35

上一章中,我使用Unity重构了解决方案。不过在Application工程中仍然需要引用其他各个依懒项。很明显,这样做并不能实现计算器模块的可插拔。今天,将以此为目标,对该解决方案进行再次的重构。 

首先,在使用Prism框架加载的程序集中分别添加一个类,并让这些类实现IModule接口。当Prism框架加载某个程序集后,将首先在程序集中搜索实现了该接口的类。之后将会调用该接口的Initialize方法。于是,我们可以在这个方法中实现程序集内部的初化始操作,或者执行某个动作。通过这种机制,可以实现程序集的完全解藕。具体的操作如下:

 

1. 在CalculatorLibrary 程序集中添加一个类:CalculatorModule,并让其实现IModule接口。代码如下:

 2      public  class 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接口。代码如下:

 2      public  class 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接口。代码如下:

 2      public  class InputParsingModule : 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方法中将会启动计算器。代码如下:

 2      public  class MainModule: IModule
 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方法中启动计算器。这里的代码在上一章中基本都用过,在此不再描述。 

 

经过上面的修改,我们可以非常方便的对其进行调用,并且不需要任何的引用,实现了完全的解藕。下面的代码,将指示我们如何在主程序中启动这些程序集。如下:

 2      static  void Main( string[] args)
 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文件:

  2  <? xml version="1.0" encoding="utf-8"  ?>
 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框架,共同进步。请大家多多指教。

 

在此,奉上该解决方案的源码:请点击  这里 下载。