7模块化Modules Prism官网案例学习

声明

原文出处如下:

作者:RyzenAdorer 内容简介:Prism医疗案例

作者:可是我爱你啊 内容简介:Prism官方案例的学习分享

Prism官网开发文档

容器相关知识的学习

Microsoft官方文档

这是一篇记录作者学习Prism的随笔,该随笔的内容是作者通过5个资源学习汇总而成,主要是为了方便自己以后拾遗温习所用,如果文中内容看不懂,推荐直接阅读相关原文。

Prism官网案例学习7-8模块化Modules

创建引入模块

  1. prism模板创建模块-》并在内部初始化模块

    public void OnInitialized(IContainerProvider containerProvider)
    {
    var regionManager = containerProvider.Resolve<IRegionManager>();
    regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
    }
    
  2. 依赖项添加项目引用

  3. App.xaml.cs中注册模块,设置为按需加载

    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
      var moduleType = typeof(ModuleAModule);
      moduleCatalog.AddModule(new ModuleInfo()
      {
         ModuleName = moduleType.Name,
         ModuleType = moduleType.AssemblyQualifiedName,
         InitializationMode = InitializationMode.OnDemand,
       });
    }
    
  4. MainWondow.xaml.cs中加载模块

     public partial class MainWindow : Window
        {
            IModuleManager _moduleManager;
    
            public MainWindow(IModuleManager moduleManager)
            {
                InitializeComponent();
                _moduleManager = moduleManager;
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                _moduleManager.LoadModule("ModuleAModule");
            }
        }
    

注册/发现模块->三种方式

代码注册

代码注册是没有所谓的发现模块部分,是直接开始注册,ViewModels中使用命令添加时,需要在MainWindowViewModel中_moduleManager = moduleManager;

  1. 注册模块:

    //直接
    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
    	moduleCatalog.AddModule<ModuleA.ModuleAModule>();
    }
    
    //按需
    Copyprotected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
    //直接
    moduleCatalog.AddModule<PrismMetroSample.PatientModule.PatientModule>();  
    //将MedicineModule模块设置为按需加载
        //反射获取模块信息
    var MedicineModuleType = typeof(PrismMetroSample.MedicineModule.MedicineModule);
    	//设置为按需加载
    moduleCatalog.AddModule(new ModuleInfo()
    {		//模块名
            ModuleName= MedicineModuleType.Name,
        	//模块类型
            ModuleType=MedicineModuleType.AssemblyQualifiedName,
        	//按需加载		初始化模式=按需
            InitializationMode=InitializationMode.OnDemand
        });
                
     }
    
    //-------------------------官方按需
    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        //反射获取模块信息
    	var moduleAType = typeof(ModuleAModule);
        //添加对应的模块信息
    	moduleCatalog.AddModule(new ModuleInfo()
    		{
    			ModuleName = moduleAType.Name,
    			ModuleType = moduleAType.AssemblyQualifiedName,
    			InitializationMode = InitializationMode.OnDemand
    		});
    }
    

目录文件扫描注册

  1. 注册模块:

    • 设置是否按需加载:首先我们先在MedicineModule加上特性,OnDemand为true为"按需"加载,而PatientModule默认加载则可以不加

      Copy [Module(ModuleName = "MedicineModule", OnDemand =true)]//设置是否按需加载
      public class MedicineModule : IModule
      
    • 生成事件DLL,拷贝到PrismMetroSample.Shell项目bin\Debug下的Modules文件夹下

      我们将PrismMetroSample.MedicineModule项目和PrismMetroSample.PatientModule项目设置生成事件dll拷贝到PrismMetroSample.Shell项目bin\Debug下的Modules文件夹下

      //生成事件命令行
      Copyxcopy "$(TargetDir)$(TargetName)*$(TargetExt)" "$(SolutionDir)\PrismMetroSample.Shell\bin\Debug\netcoreapp3.1\Modules\" /Y /S
      
  2. 发现模块:

    • 在App.xaml.cs重载实现该函数:

      protected override IModuleCatalog CreateModuleCatalog(){
      //获取该路径下的文件夹的模块目录
      return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
      }
      

初始化模块->使用配置文件App.config注册

  1. 注册模块:创建App.config文件,初始化模块->使用配置文件App.config注册

    //注册模块
    <module assemblyFile="ModuleA.dll" moduleType="ModuleA.ModuleAModule, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ModuleAModule" startupLoaded="True" />
    
    
  2. 发现模块:

    protected override IModuleCatalog CreateModuleCatalog()
    {
    	return new ConfigurationModuleCatalog();//加载配置文件模块目录
    }
    

加载模块

prism应用程序加载模块有两种方式:

  • 加载“可用时”的模块(默认方式)
  • 根据情况加载“按需”模块

在代码注册时候,我将通过默认方式注册了PatientModule,然后注册MedicineModule将其设置为"按需"加载,“按需”加载有个好处就是,应用程序运行初始化后,MedicineModule模块是不加载到内存的,这样就提供了很大的灵活空间,默认我们可以加载一些"可用"的模块,然后我们可以根据自身要求去"按需"加载我们所需要的模块

这里可以讲解下按需加载MedicineModule的代码实现,首先我们已经在App.cs中将MedicineModule设置为"按需"加载,然后我们在主窗体通过一个按钮去加载MedicineModule,代码如下: MainWindowViewModle.cs:

Copy public class MainWindowViewModel : BindableBase
 {
 	//模块管理器字段
    IModuleManager _moduleManager;
    public MainWindowViewModel(IModuleManager moduleManager)
    {
       _moduleManager = moduleManager;
    }
	
    private DelegateCommand _loadPatientModuleCommand;
    public DelegateCommand LoadPatientModuleCommand =>
        _loadPatientModuleCommand ?? (_loadPatientModuleCommand = new DelegateCommand(ExecuteLoadPatientModuleCommand));

    void ExecuteLoadPatientModuleCommand()
    {
    //加载模块
       _moduleManager.LoadModule("MedicineModule");
    }
 }

我们还可以去检测加载模块完成事件,我们MainWindowViewModle中加上这几句:

CopyIModuleManager _moduleManager;
public MainWindowViewModel(IModuleManager moduleManager)
{
   _moduleManager = moduleManager;
   _moduleManager.LoadModuleCompleted += _moduleManager_LoadModuleCompleted;
}

private void _moduleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)
{
   MessageBox.Show($"{e.ModuleInfo.ModuleName}模块被加载了");
}

初始化模块

示例1

新增一个类ModuleAModule.cs实现IModule接口(每一个Module类都要实现这个接口,而每一个Module都要有这样一个类来对Module里的资源统一管理)

namespace ModuleA
{
    public class ModuleAModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {
            var regionManager = containerProvider.Resolve<IRegionManager>();
            regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            
        }
    }
}

示例2

加载模块后,模块就会进行初始化,我们以MedicineModule为例子,先来看看代码:

Copy public class MedicineModule : IModule
 {
     public void OnInitialized(IContainerProvider containerProvider)
     {
var regionManager = containerProvider.Resolve<IRegionManager>();


//MedicineMainContent 医学内容       regionManager.RegisterViewWithRegion(RegionNames.MedicineMainContentRegion, typeof(MedicineMainContent));

//SearchMedicine-Flyout 探诊
regionManager.RegisterViewWithRegion(RegionNames.FlyoutRegion, typeof(SearchMedicine));

//rightWindowCommandsRegion 右翼突击队regionManager.RegisterViewWithRegion(RegionNames.ShowSearchPatientRegion, typeof(ShowSearchPatient));
      }


	public void RegisterTypes(IContainerRegistry containerRegistry)
	{
            
	}
}

其中,IModule接口定义了两个函数OnInitialized和RegisterTypes,其中初始化顺序是RegisterTypes->OnInitialized,也就是RegisterTypes函数会先于OnInitialized函数,虽然这里我没在RegisterTypes写代码,但是这里通过是可以依赖注入到容器,给MedicineModule模块使用的,而OnInitialized我们通常会注册模块试图,或者订阅应用程序级别的事件和服务,这里我是将三个View分别分区域注册模块视图。

posted @ 2020-08-10 01:44  AJun816  阅读(371)  评论(0编辑  收藏  举报