WPF入门到跪下 第十一章 Prism(八)模块化管理-Module

模块化管理-Model

Module是功能和资源的逻辑集合,其打包方式可以单独开发、测试、部署并集成到应用程序中。

当随着项目较为庞大,有大量的不同业务、ViewViewModel时,就需要考虑根据不同业务进行程序集的拆分了,而Module就是帮助我们管理不同的程序集并集成到应用程序中。

每个模块化管理的程序集中都有一个模块核心类,IModule的子类。主程序集通过加载这个IModule的子类,就可以将对应程序集集成到主程序集的prism框架中来。

一、简单使用

这里以主程序使用其他模块管理的程序集中的Region视图为例进行Module的简单使用。

首先在主程序集所在的解决方案中添加新的WPF用户控件库、创建Views与ViewModels文件夹、引入prism.Unity库。

在这里插入图片描述

①、View层

在Views中添加将要使用用户控件ViewA

<UserControl ......>
    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding Value}"/>
        </StackPanel>
    </Grid>
</UserControl>

②、ViewModel层

在ViewModels中创建对应的视图模型ViewAViewModel

public class ViewAViewModel:BindableBase
{
    private string _value = "这里是ViewA";

    public string Value
    {
        get { return _value; }
        set 
        {
            SetProperty(ref _value, value); 
        }
    }
}

③、实现IModule

在程序集中创建SubModule实现IModule接口,其内含以下两个函数:

  • OnInitialized(IContainerProvider containerProvider):当模块初始化时调用,可以处理一些业务逻辑。
  • RegisterTypes(IContainerRegistry containerRegistry):进行类型注册,与主程序集中App后台代码的RegisterTypes函数作用差不多的。

RegisterTypes函数中,通过IContainerRegistry对象的RegisterForNavigation方法注册ViewA类型。

OnInitialized函数中,进行区域的初始化加载,如果使用模块化管理,那么RegionView的初始化加载时机最好是放在Module中执行,这样的好处在于,当主程序无法顺利加载Module时,不会因此而抛出异常。而且思路跟整体性会较好。

public class SubModule : IModule
{
    public void OnInitialized(IContainerProvider containerProvider)
    {
        //在这里进行区域的初始化加载个人认为是一个比较好的做法
		var regionManager = containerProvider.Resolve<IRegionManager>();
        regionManager.RegisterViewWithRegion("LeftMenuTreeRegion", typeof(TreeMenuView)); //LeftMenuTreeRegion是主程序中的Region名
		//此外,模块初始化时可以在这里进行一些业务处理
				
    }

    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        //进行类型注册,与主程序集中App的RegisterTypes函数作用差不多的。
        //containerRegistry.RegisterForNavigation<Views.ViewA>();  这里由于OnInitialized函数中使用了RegisterViewWithRegion方法来加载区域,所以不用再注册
    }
}

④、加载Module

在主程序集的App后台代码中重写ConfigureModuleCatalog方法,并通过该方法的参数IModuleCatalog对象的AddModule方法进行Module类型的注册。

AddModule<T>():加载Module类型,泛型T为要加载的Module类型。

public partial class App : PrismApplication
{
    ......
    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        moduleCatalog.AddModule<Sub.SubModule>();
    }
}

⑤、使用视图

在主程序集中正常使用即可

  • MainWindow.xaml
<Window ......
        xmlns:prism="http://prismlibrary.com/">
    <Grid>
        <StackPanel>
            <Button Content="ModuleButton" Command="{Binding BtnCommand}"/>
            <ContentControl prism:RegionManager.RegionName="MainRegion"/>
        </StackPanel>
    </Grid>
</Window>
  • MainWindowViewModel.cs
public class MainWindowViewModel:BindableBase
{
    [Dependency]
    public IRegionManager regionManager { get; set; }
    public ICommand BtnCommand { 
        get => new DelegateCommand(() =>
        {
            regionManager.RequestNavigate("MainRegion", "ViewA");
        }); 
    }
}

二、4种Module加载方式

1、AddModule的泛型方法

在主程序集的App后台代码中重写ConfigureModuleCatalog方法,并通过该方法的参数IModuleCatalog对象的AddModule<T>方法进行Module类型的加载。

AddModule<T>():加载Module类型,泛型T为要加载的Module类型。

上文例子中使用的就是这种方法,这里就不再举例了。

2、AddModule的非泛型方法

在主程序集的App后台代码中重写ConfigureModuleCatalog方法,并通过该方法的参数IModuleCatalog对象的非泛型函数AddModule进行Module类型的加载。

AddModule(IModuleInfo moduleInfo):加载Module类型,需要加载的Module类型的信息存放在参数moduleInfo中。

public partial class App : PrismApplication
{
......
    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        Type type = typeof(Sub.SubModule);
        moduleCatalog.AddModule(new ModuleInfo { 
            ModuleName = "Hello",
            ModuleType = type.AssemblyQualifiedName
        });
    }
}

需要注意,创建ModuleInfo类型时,ModuleName必须进行初始化,否则会报错。

3、配置文件方式

配置文件的方式可以使用App.config进行配置,也可以使用xml文件的方式。

①、Module配置

App.config方式:在主程序集的应用配置文件App.config(如果没有则添加)中进行module配置。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
		<section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf"/>
	</configSections>
	<modules>
		<module assemblyFile="PrismModule.Sub"
				moduleType="PrismModule.Sub.SubModule, PrismModule.Sub, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
				moduleName="ViewAModule"/>
	</modules>
</configuration>

XML文件方式:在主程序集下新建ModuleConfig文件夹并在文件夹内创建ModuleConfig.xml进行配置,然后将该文件属性设置为资源。

<?xml version="1.0" encoding="utf-8" ?>
<m:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:m="clr-namespace:Prism.Modularity;assembly=Prism.Wpf">
	<m:ModuleInfo ModuleName="ViewAModule"
                  ModuleType="PrismModule.Sub.SubModule, PrismModule.Sub, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</m:ModuleCatalog>

PS:moduleType看起来很长,但不需要死记,其实就是方式2中的ModuleType

②、加载模块

在主程序集的App后台代码中重写CreateModuleCatalog方法并返回一个新创的ConfigurationModuleCatalog对象即可。

public partial class App : PrismApplication
{
    ......
    protected override IModuleCatalog CreateModuleCatalog()
	{
		//App.config配置方式的module加载
	    return new ConfigurationModuleCatalog();
		//xml文件配置方式的module加载
	    //return new XamlModuleCatalog(new Uri("/PrismModule.Sub;component/ModuleConfig/ModuleConfig.xml"));
	}
}

4、扫描指定目录方式(常用)

除了上面三种加载方式外,还有一种更加解耦、更加方便的方式,就是指定Module所在目录,让程序自动去扫描并加载Module,做法很简单,只需要在主程序集的App后台代码中重写CreateModuleCatalog方法并返回一个包含Module存放路径信息的DirectoryModuleCatalog对象即可。

需要注意,这种方式要在编译后将需要使用的模块程序集的dll文件放置到对应目录下,一般会在Debug目录下新建Moduls,并将编译后的需要使用的模块对应程序集dll文件放入其中。

在这里插入图片描述

public partial class App : PrismApplication
{
    ......
    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new DirectoryModuleCatalog()
        {
           //表示扫描程序运行目录下的Modules文件夹,也就是Debug最里层目录下的Modules文件夹
            ModulePath = ".\\Modules"
        };
    }
}

使用这种方式的好处在于,可以最大程度的让主程序集跟其他模块程序集保持解耦状态。

  • 程序集编译成功后自动将dll文件放入指定目录的设置:进入程序集的属性设置,在生成后事件中输入copy $(TargetPath) $(SolutionDir)Client\bin\Debug\net6.0-windows\Modules\$(TargetFileName) /Y,其中Client\bin\Debug\net6.0-windows\Modules\为解决方案下的指定目录
    在这里插入图片描述

三、按需加载(懒加载)

Prism框架中,对于Module的使用默认情况下是采用预加载的,但也提供了懒加载的方案,只需要在添加Module类型的时候设置为懒加载,然后在使用module前通过IModuleManager对象的LoadModule(moduleName)方法进行加载即可。

1、懒加载设置

上文学习的4种加载方式都能设置为懒加载,具体如下:

①、AddModule的泛型方法

AddModule<T>(string name, InitializationMode mode):加载模块,T为要加载的模块类型。

  • name:主动加载模块时使用的模块名称。
  • mode:加载模式,默认为预加载模式,InitializationMode.OnDemand为懒加载。

public partial class App : PrismApplication
{
    ......
    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        moduleCatalog.AddModule<Sub.SubModule>("ViewAModule", InitializationMode.OnDemand);
    }
}

②、AddModule的非泛型方法

创建ModuleInfo时,在初始化器中将InitializationMode属性设置为InitializationMode.OnDemand

public partial class App : PrismApplication
{
    ......

    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        moduleCatalog.AddModule(new ModuleInfo
        {
            ModuleName = "ViewAModule",
            ModuleType = typeof(Sub.SubModule).AssemblyQualifiedName,
            InitializationMode = InitializationMode.OnDemand
        });
    }
}

③、配置文件方式

在配置文件的module节点上,设置属性startupLoaded="false”

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
		<section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf"/>
	</configSections>
	<modules>
		<module assemblyFile="PrismModule.Sub"
				moduleType="PrismModule.Sub.SubModule, PrismModule.Sub, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
				moduleName="ViewAModule"
				startupLoaded="false"/>
	</modules>
</configuration>

④、扫描目录方式

扫描目录的方式要实现懒加载需要在对应的IModule实现类上使用特性[Module(ModuleName ="ViewAModule", OnDemand =true)]进行标识

[Module(ModuleName ="ViewAModule", OnDemand =true)]
public class SubModule : IModule
{
    ......
}

2、使用前进行加载

通过IOC依赖注入获得IModuleManager对象属性,然后调用LoadModule方法即可。

public class MainWindowViewModel:BindableBase
{
    [Dependency]
    public IRegionManager regionManager { get; set; }
    [Dependency]
    public IModuleManager moduleManager { get; set; }
    public ICommand BtnCommand { 
        get => new DelegateCommand(() =>
        {
            moduleManager.LoadModule("ViewAModule");
            regionManager.RequestNavigate("MainRegion", "ViewA");
        }); 
    }
}
  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
WPF(Windows Presentation Foundation)是一种用于创建Windows桌面应用程序的开发框架,而Prism是一个用于帮助开发人员构建可扩展、模块化WPF应用程序的框架。 在WPF Prism中,模块是应用程序的组成部分,每个模块都是相对独立、可重用且可扩展的。模块可以使用Prism框架提供的功能进行加载和管理。 模块加载的过程包括以下步骤: 1. 定义模块:首先,需要在应用程序中定义模块。模块通常包括一个模块类,该类实现了IModule接口,并在其中进行模块的初始化工作。 2. 配置模块目录:为了加载模块,需要指定模块所在的目录。可以在应用程序的配置文件中设置模块目录的路径。 3. 模块发现:Prism框架将会在指定的模块目录中查找模块,并获取模块的配置信息。 4. 模块加载:根据模块的配置信息,Prism框架将逐个加载模块。加载过程会创建模块的实例,并在应用程序中进行初始化。 5. 模块初始化:一旦模块被加载,Prism框架将调用模块的初始化方法,用于注册模块的服务、视图等。 通过这种方式,应用程序可以使用Prism框架来实现模块化的架构。模块可以根据需求进行动态加载和卸载,以实现更好的应用程序可扩展性和维护性。 总结起来,WPF Prism模块加载的过程涉及定义模块、配置模块目录、模块发现、模块加载和模块初始化等步骤。通过这些步骤,开发人员可以构建出可扩展、模块化WPF应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SchuylerEX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值