1.概要

  Module,具有特定功能,且独立存在则称为成为模块。下图为Prism体系中的关系结构图。

  

  在Prism体系中Module的应用分为

  注册/发现模块

  加载模块

  初始化模块

  

  2.详细内容

  (1)注册/发现模块

  通过重写CreateModuleCatalog方法指定加载module的方式,这里我个人比较推荐使用反射的方式去指定目录下读取,当然还有其他方式这里就不一 一介绍了。

  首先我们将项目中的module编译生成到项目运行目录下的Apps文件夹下。

  

  这时需要在类库右键->点击属性。

  

  将DLL编译生成时拷贝到,指定目录下(详情见源码)。

  ///

  /// Interaction logic for App.xaml

  ///

  public partial class App

  {

  ///

  /// 应用程序启动时创建Shell

  ///

  ///

  protected override Window CreateShell

  {

  return Container.Resolve;

  }

  protected override void RegisterTypes(IContainerRegistry containerRegistry)

  {

  //注册服务、依赖、View

  }

  ///

  /// 配置区域适配

  ///

  ///

  protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)

  {

  base.ConfigureRegionAdapterMappings(regionAdapterMappings);

  }

  protected override IModuleCatalog CreateModuleCatalog

  {

  //new ConfigurationModuleCatalog

  //指定模块加载方式为从文件夹中以反射发现并加载module(推荐用法)

  return new DirectoryModuleCatalog { ModulePath=@".\Apps" };

  }

  }

  (2)加载模块

  加载模块的代码实现在DirectoryModuleCatalog内部实现大致如下:

  //

  // Summary:

  // Represets a catalog created from a directory on disk.

  //

  // Remarks:

  // The directory catalog will scan the contents of a directory, locating classes

  // that implement Prism.Modularityodule and add them to the catalog based on

  // contents in their associated Prism.Modularity.ModuleAttribute. Assemblies are

  // loaded into a new application domain with ReflectionOnlyLoad. The application

  // domain is destroyed once the assemblies have been discovered. The diretory catalog

  // does not continue to monitor the directory after it has created the initialze

  // catalog.

  publicclassDirectoryModuleCatalog:ModuleCatalog

  {

  privateclassInnerModuleInfoLoader:MarshalByRefObject

  {

  internal ModuleInfo GetModuleInfos(string path)

  {

  DirectoryInfo directory=newDirectoryInfo(path);

  ResolveEventHandlervalue=(objectsender, ResolveEventArgs args)=> OnReflectionOnlyResolve(args, directory);

  AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve +=value;

  ModuleInfo result=GetNotAlreadyLoadedModuleInfos(IModuleType: AppDomain.CurrentDomain.GetAssemblies.First((Assembly asm)=> asm.FullName==typeof(IModule).Assembly.FullName).GetType(typeof(IModule).FullName), directory: directory).ToArray;

  AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -=value;

  returnresult;

  }

  private static IEnumerable GetNotAlreadyLoadedModuleInfos(DirectoryInfo directory, Type IModuleType)

  {

  List list=newList;

  Assembly alreadyLoadedAssemblies=(frompinAppDomain.CurrentDomain.GetAssemblies

  where!p.IsDynamic

  selectp).ToArray;

  foreach(FileInfo item in (from file in directory.GetFiles("*.dll")

  where alreadyLoadedAssemblies.FirstOrDefault((Assembly assembly)=>stringpare(Path.GetFileName(assembly.Location), file.Name, StringComparison.OrdinalIgnoreCase)==0)==

  selectfile).ToList)

  {

  try

  {

  list.Add(Assembly.LoadFrom(item.FullName));

  }

  catch(BadImageFormatException)

  {

  }

  }

  returnlist.SelectMany((Assembly assembly)=>fromtinassembly.GetExportedTypes.Where(newFunc(IModuleType.IsAssignableFrom))

  wheret !=IModuleType

  where!t.IsAbstract

  select t into type

  select CreateModuleInfo(type));

  }

  private static Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)

  {

  Assembly assembly=AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies.FirstOrDefault((Assembly asm)=>string.Equals(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase));

  if(assembly !=)

  {

  returnassembly;

  }

  AssemblyName assemblyName=newAssemblyName(args.Name);

  stringtext=Pathbine(directory.FullName, assemblyName.Name + ".dll");

  if(File.Exists(text))

  {

  returnAssembly.ReflectionOnlyLoadFrom(text);

  }

  returnAssembly.ReflectionOnlyLoad(args.Name);

  }

  internal void LoadAssemblies(IEnumerable assemblies)

  {

  foreach(stringassemblyinassemblies)

  {

  try

  {

  Assembly.ReflectionOnlyLoadFrom(assembly);

  }

  catch(FileNotFoundException)

  {

  }

  }

  }

  private static ModuleInfo CreateModuleInfo(Type type)

  {

  stringname=type.Name;

  List list=newList;

  boolflag=false;

  CustomAttributeData customAttributeData=CustomAttributeData.GetCustomAttributes(type).FirstOrDefault((CustomAttributeData cad)=> cad.Constructor.DeclaringType!.FullName==typeof(ModuleAttribute).FullName);

  if(customAttributeData !=)

  {

  foreach(CustomAttributeNamedArgument namedArgumentincustomAttributeData.NamedArguments)

  {

  switch(namedArgument.MemberInfo.Name)

  {

  case"ModuleName":

  name=(string)namedArgument.TypedValue.Value;

  break;

  case"OnDemand":

  flag=(bool)namedArgument.TypedValue.Value;

  break;

  case"StartupLoaded":

  flag=!(bool)namedArgument.TypedValue.Value;

  break;

  }

  }

  }

  foreach(CustomAttributeData iteminfromcadinCustomAttributeData.GetCustomAttributes(type)

  wherecad.Constructor.DeclaringType!.FullName==typeof(ModuleDependencyAttribute).FullName

  selectcad)

  {

  list.Add((string)item.ConstructorArguments[0].Value);

  }

  ModuleInfo obj=newModuleInfo(name, type.AssemblyQualifiedName)

  {

  InitializationMode=(flag ? InitializationMode.OnDemand : InitializationMode.WhenAvailable),

  Ref=type.Assembly.EscapedCodeBase

  };

  obj.DependsOn.AddRange(list);

  returnobj;

  }

  }

  //

  // Summary:

  // Directory containing modules to search for.

  publicstringModulePath

  {

  get;

  set;

  }

  //

  // Summary:

  // Drives the main logic of building the child domain and searching for the assemblies.

  protected override void InnerLoad

  {

  if(string.IsOrEmpty(ModulePath))

  {

  thrownewInvalidOperationException(Prismperties.Resources.ModulePathCannotBeOrEmpty);

  }

  if(!Directory.Exists(ModulePath))

  {

  thrownewInvalidOperationException(string.Format(CultureInfo.CurrentCulture, Prismperties.Resources.DirectoryNotFound, ModulePath));

  }

  AppDomain currentDomain=AppDomain.CurrentDomain;

  try

  {

  List list=newList;

  IEnumerable collection=fromAssembly assemblyinAppDomain.CurrentDomain.GetAssemblies

  where!(assemblyisAssemblyBuilder) && assembly.GetType.FullName !="System.Reflection.Emit.InternalAssemblyBuilder" && !string.IsOrEmpty(assembly.Location)

  selectassembly.Location;

  list.AddRange(collection);

  Type typeFromHandle=typeof(InnerModuleInfoLoader);

  if(typeFromHandle.Assembly !=)

  {

  InnerModuleInfoLoader innerModuleInfoLoader=(InnerModuleInfoLoader)currentDomain.CreateInstanceFrom(typeFromHandle.Assembly.Location, typeFromHandle.FullName)!.Unwrap;

  base.Items.AddRange(innerModuleInfoLoader.GetModuleInfos(ModulePath));

  }

  }

  catch(Exception innerException)

  {

  thrownewException("There was an error loading assemblies.", innerException);

  }

  }

  }

  (3)初始化模块

  这些代码在使用Prism项目模板创建Module的时候就已经自动创建好了。

  [Module(ModuleName="Contact")]

  public class ContactModule : IModule

  {

  //初始化

  public void OnInitialized(IContainerProvider containerProvider)

  {

  //通过注册RegionManager,添加ContactView

  var regionManager=containerProvider.Resolve;

  //通过ContentRegion管理导航默认初始页面ContactView

  var contentRegion=regionManager.Regions["ContentRegion"];

  contentRegion.RequestNavigate(nameof(ContactView));

  }

  public void RegisterTypes(IContainerRegistry containerRegistry)

  {

  containerRegistry.RegisterForNavigation;

  }

  }

  3.实战应用

  Shell - MainWindow实现

  

  

  

  

  

  

  

  

  

  

  

  

  MainWindowViewModel中的实现

  public class MainWindowViewModel : BindableBase

  {

  private string _title="Prism Application";

  //Region管理对象

  private IRegionManager _regionManager;

  private IModuleCatalog _moduleCatalog;

  private ObservableCollection _modules;

  private DelegateCommand _loadModules;

  private IModuleInfo _moduleInfo;

  public IView View { get; set; }

  public string Title

  {

  get { return _title; }

  set { SetProperty(ref _title, value); }

  }

  public ObservableCollection Modules

  {

  get=> _modules (_modules=new ObservableCollection);

  }

  public DelegateCommand LoadModules { get=> _loadModules=new DelegateCommand(InitModules); }

  public IModuleInfo ModuleInfo

  {

  get

  {

  return _moduleInfo;

  }

  set

  {

  _moduleInfo=value;

  Navigate(value);

  }

  }

  public MainWindowViewModel(IRegionManager regionManager, IModuleCatalog moduleCatalog)

  {

  _regionManager=regionManager;

  _moduleCatalog=moduleCatalog;

  }

  public void InitModules

  {

  var dirModuleCatalog=_moduleCatalog as DirectoryModuleCatalog;

  Modules.AddRange(dirModuleCatalog.Modules);

  }

  private void Navigate(IModuleInfo info)

  {

  _regionManager.RequestNavigate("ContentRegion", $"{ info.ModuleName }View");

  }

  }

  Module - Wemail.Contact实现

  ContactModule.cs 模块标记文件

  [Module(ModuleName="Contact")]

  public class ContactModule : IModule

  {

  public void OnInitialized(IContainerProvider containerProvider)

  {

  //通过注册RegionManager,添加ContactView

  var regionManager=containerProvider.Resolve;

  //通过ContentRegion管理导航默认初始页面ContactView

  var contentRegion=regionManager.Regions["ContentRegion"];

  contentRegion.RequestNavigate(nameof(ContactView));

  }

  public void RegisterTypes(IContainerRegistry containerRegistry)

  {

  containerRegistry.RegisterForNavigation;

  }

  }

  ContactView实现

  

  

  

  

  

  

  

  

  ContactViewModel实现

  public class ContactViewModel : BindableBase

  {

  private ObservableCollection _contacts;

  private string _message;

  public string Message

  {

  get { return _message; }

  set { SetProperty(ref _message, value); }

  }

  public ObservableCollection Contacts

  {

  get=> _contacts (_contacts=new ObservableCollection);

  }

  public ContactViewModel

  {

  Message="Wemail.Contact Prism Module";

  Contacts.Add("联系人张某");

  Contacts.Add("联系人王某");

  }

  }

04Prism WPF 入门实战 - Module相关推荐

  1. 03Prism WPF 入门实战 - Region

    1.概要 源码及PPT地址:https://github.com/JusterZhu/wemail 视频地址:https://www.bilibili.com/video/BV1KQ4y1C7tg?s ...

  2. 01Prism WPF 入门实战 - 项目准备

    1.概要 这一系列将进行Prism+WPF技术的实战讲解.实战项目内容选型为Email邮件收发的客户端(WeMail),项目结构简单方便大家理解. 相关技术:C#.WPF.Prism 软件开发环境:V ...

  3. 06Prism WPF 入门实战 - Log控件库

    1.概要 源码及PPT地址:https://github.com/JusterZhu/wemail 视频地址:https://www.bilibili.com/video/BV1KQ4y1C7tg?s ...

  4. 05Prism WPF 入门实战 - Navigation

    1.概要 源码及PPT地址:https://github.com/JusterZhu/wemail 视频地址:https://www.bilibili.com/video/BV1KQ4y1C7tg?s ...

  5. 02Prism WPF 入门实战 - 建项

    1.概要 Prism介绍 Github:  https://github.com/PrismLibrary/Prism 开发文档:https://prismlibrary.com/docs/ Pris ...

  6. WPF入门教程-转载

    最近为了做炫酷的UI,了解了WPF,之前一直是使用winform的,界面也是古老的不行. 在园里找到了一个大佬以前写的教程,备注一下.按照系列教程走下来,可以直接上手了. 备忘传送门>>& ...

  7. 自然语言处理入门实战2:基于深度学习的文本分类

    自然语言处理入门实战2:基于深度学习的文本分类 数据集 数据预处理 模型 模型训练 模型测试 参考 本文参考复旦大学自然语言处理入门练习,主要是实现基于深度学习的文本分类. 环境:python3.7 ...

  8. SO逆向入门实战教程一:OASIS

    文章目录 一.前言 二.准备 三.Unidbg模拟执行 四.ExAndroidNativeEmu 模拟执行 五.算法分析 六.尾声 一.前言 这是SO逆向入门实战教程的第一篇,总共会有十三篇,十三个实 ...

  9. Pytorch入门+实战系列七:图片风格迁移和GAN

    Pytorch官方文档:https://pytorch.org/docs/stable/torch.html? 1. 写在前面 今天开始,兼顾Pytorch学习, 如果刚刚接触深度学习并且想快速搭建神 ...

最新文章

  1. CentOS7(64位)安装NVIDIA显卡驱动和CUDA8.0
  2. Android-Toolbar相关
  3. 以下可以采用python语言保留字的是-模拟试卷C单项选择题
  4. Android之动态改变控件大小
  5. 小说形象特征包括哪些方面_中高考常考题:怎样鉴赏散文中的形象 ?
  6. python中print是什么意思_python中print什么意思
  7. Leetcode--229. 求众数Ⅱ
  8. 《需求工程——软件建模与分析》阅读笔记之二
  9. 分布式监控系统ganglia配置文档
  10. AndroidStudio_androidstudio连接华为 HUAWEI Mate平板_调试测试---Android原生开发工作笔记143
  11. delphi 的插件机制与自动更新
  12. 【java】Java泛型
  13. 阶段3 1.Mybatis_01.Mybatis课程介绍及环境搭建_02.三层架构和ssm框架的对应关系
  14. 天翼如何才能鹏程×××?
  15. angularJS 双向数据绑定、作用域、表达式、
  16. Latice CPLD jed转VME文件简介
  17. 全国大学生数学建模竞赛论文格式规范
  18. Android webview与js交互
  19. python接入图灵机器人_Python使用微信接入图灵机器人过程解析
  20. 村上春树 --《当我谈跑步时,我谈些什么》句子摘录​

热门文章

  1. 图解 Numpy,原来数据操作这么简单!
  2. 这款网络排查工具,堪称神器!
  3. matlab imread_matlab经典图片生成与去水印
  4. 江苏机器人竞赛南航_中国青少年机器人竞赛
  5. 深度学习-Tensorflow2.2-深度学习基础和tf.keras{1}-逻辑回归与交叉熵概述-05
  6. ajax请求后台表格数据,商品后台表格数据的展现方式
  7. [Linux] nginx的try_files指令实现隐藏index.php的重写
  8. html2canvas解决保存图片模糊问题
  9. NumPy - 字符串函数
  10. sqlplus操作--文件的输入与输出