• Prism V2之旅(5)


       上篇介绍了WPF的Attach Behavior(附加行为)模式以及如何在prism框架中如何使用附加行为和RegionAdapter的扩展.

    这篇来介绍Prism中的很重要的一个功能模块化.

    请下载Demo

    基本概念

    模块化的概念类似于现在网上比较流行的Widget,如下例子

    google的个性化页面

    image

    vista的sidebar

    image

    他们都有如下特性:

    1.模块之间没有关联,模块之间不会相互引用

    2.可插拔(可随意增删改模块)

    使用prism框架,模块是基础,一个系统是由多个模块组成,一个模块可以代表一个子功能,很重要的是这样的做法可以降低开发的复杂度.下面我们来了解在prism中,模块的基本使用方法.

    1.注册模块

    prism定义了一个IModule接口,Initialize方法是模块初始化的入口点,好比主程序的Main的入口点.

    image

    一般情况下,每新建一个模块都会新建一个项目来完成(当然这不是必须的规定).下面是一个简单的例子

    public class ModuleA : IModule
    {
        private readonly IRegionManager regionManager;
    
        public ModuleA(IRegionManager regionManager)
        {
            this.regionManager = regionManager;
        }
    
        public void Initialize()
        {
            this.regionManager.Regions["MainRegion"].Add(new DefaultViewA());
        }
    }

    在模块初始化的时候,可以在依赖注入容器中获取已注册的服务

    加载模块的方式有三种

    • 静态加载模块
    • 根据目录加载模块
    • 根据配置文件加载模块

    image

    加载模块现在有以下概念:

    • 模块添加方法
    • 模块依赖性
    • 模块加载方式

    2.加载模块之静态加载模块

    2.1重写Bootstrapper的GetModuleCatalog方法

    在Bootstrapper引导程序中重写GetModuleCatalog方法,返回一个实现IModuleCatalog的对象,静态加载模块请返回ModuleCatalog

    protected override IModuleCatalog GetModuleCatalog()
    {
        ModuleCatalog catalog = new ModuleCatalog();
        catalog.AddModule(typeof (ModuleA), "ModuleD")
            .AddModule(typeof (ModuleB))
            .AddModule(typeof (ModuleD), "ModuleB")
            .AddModule(typeof (ModuleC), InitializationMode.OnDemand)
            ;
            
        return catalog;
    }

    2.2模块依赖(dependsOn)

    AddModule方法,第一个参数是模块类型,第二个是该模块依赖的模块.如上ModuleA依赖于ModuleD,ModuleD依赖于ModuleB.所以上面的加载顺序如下.模块依赖在不同加载模块的方式都有,只不过做法不同而已

    image

    2.3加载方式(初始化加载和按需加载)

    (1)初始化加载

    InitializationMode决定模块是否初始化时加载,默认是WhenAvailable,OnDemand则会在请求时加载

    public enum InitializationMode
    {
        /// <summary>
        /// The module will be initialized when it is available on application start-up.
        /// </summary>
        WhenAvailable,
    
        /// <summary>
        /// The module will be initialized when requested, and not automatically on application start-up.
        /// </summary>
        OnDemand
    }

    以上配置,将会初始化ModuleA,B,C三个模块,ModuleC则不初始化.

    (2)按需加载

    按需加载可以减少初始化时加载模块的时间.可以在需要时使用IModuleManager接口的LoadModule方法来加载所需模块

    (注意:这里虽是延迟加载,但这个模块已经进来,就是说这个模块的dll还是被加载了,只不过没初始化而已)

    public DefaultViewB(IModuleManager moduleManager)
        : this()
    {
        this.moduleManager = moduleManager;
    }
    
    private void OnLoadModuleCClick(object sender, RoutedEventArgs e)
    {
        // This logic is placed in code-behind instead of a presenter
        // for the ease of demonstrating module loading.
        this.moduleManager.LoadModule("ModuleC");
    }

    3.加载模块之根据目录加载模块

    三个步骤

    3.1.把需要的模块放在某个目录下面

    3.2.用Attribute配置相关模块

    [Module(ModuleName = "ModuleA")]
    [ModuleDependency("ModuleD")]
    public class ModuleA : IModule
    {
        private readonly IRegionManager _regionManager;
    
        public ModuleA(IRegionManager regionManager)
        {
            _regionManager = regionManager;
        }
    
        public void Initialize()
        {
            _regionManager.Regions["MainRegion"].Add(new DefaultViewA());
        }
    }

    3.3.重写Bootstrapper的GetModuleCatalog方法返回DirectoryModuleCatalog,并指定模块目录.

    protected override IModuleCatalog GetModuleCatalog()
    {
        return new DirectoryModuleCatalog() {ModulePath = @".\Modules"};
    }

    3.加载模块之根据配置文件加载模块

    两个步骤

    3.1.配置文件

    <modules>
      <module assemblyFile="Modules/ModuleD.dll" moduleType="ModuleD.ModuleD, ModuleD" moduleName="ModuleD">
        <dependencies>
          <dependency moduleName="ModuleB"/>
        </dependencies>
      </module>
      <module assemblyFile="Modules/ModuleB.dll" moduleType="ModuleB.ModuleB, ModuleB" moduleName="ModuleB"/>
      <module assemblyFile="Modules/ModuleA.dll" moduleType="ModuleA.ModuleA, ModuleA" moduleName="ModuleA">
        <dependencies>
          <dependency moduleName="ModuleD"/>
        </dependencies>
      </module>
      <module assemblyFile="Modules/ModuleC.dll" moduleType="ModuleC.ModuleC, ModuleC" moduleName="ModuleC" startupLoaded="false"/>
    </modules>

    3.2.重写Bootstrapper的GetModuleCatalog方法返回ConfigurationModuleCatalog

    (注意startupLoaded属性如果设置为false,则该模块的dll不会加载,这有区别与静态加载的方式,这样的做法可以真正做到按需加载)

    好,这篇就写到这里.Demo是prism内置的.

  • 相关阅读:
    剑指offer分块总结----------字符串
    sizeWithFont 不是线程安全。
    《创业之路,败给了……》欠大家一个回复,及项目转让:高频彩票通、仓库管理软件
    搞懂.NET Framework 历史版本(2017年)
    DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)
    DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(2)
    MVC+EF 理解和实现仓储模式和工作单元模式
    (译文)MVC通用仓储类
    【开源】T430s光驱位支架
    【开源】讯飞VBOX改装蓝牙5.0(aptX HD)音箱
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/prism_part5.html
Copyright © 2020-2023  润新知