04Prism WPF 入门实战 - Module

  1.概要

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

  

04Prism WPF 入门实战 - Module

  在Prism体系中Module的应用分为

  注册/发现模块

  加载模块

  初始化模块

  

04Prism WPF 入门实战 - Module

  2.详细内容

  (1)注册/发现模块

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

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

  

04Prism WPF 入门实战 - Module

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

  

04Prism WPF 入门实战 - Module

  将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的时候就已经自动创建好了。

04Prism WPF 入门实战 - 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.实战应用

04Prism WPF 入门实战 - Module

04Prism WPF 入门实战 - Module

  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("联系人王某");

  }

  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF Prism是微软新一代的界面开发框架,它具有丰富的功能和灵活的架构,广泛应用于桌面应用程序和Web应用程序的开发中。朝夕停车场项目是基于WPF Prism框架的一个实战项目,它实现了停车场的智能化管理,包括车辆进入和出场的自动识别,车位的实时监测和调度,以及财务管理和数据分析等功能。 该项目的源码包含了多个模块和组件,采用了MVVM架构和依赖注入技术,使代码组织和维护非常方便。项目中的主要模块包括: 1. Shell模块:该模块是整个应用程序的容器,它提供了主窗口和导航栏等界面组件,以及对其他模块的管理和协调。 2. Home模块:该模块实现了停车场的实时监控和调度功能,包括车位的占用和空闲状态显示,车辆进出场的记录和管理,以及停车位的预定和预约等功能。 3. Financial模块:该模块实现了停车场的财务管理和数据分析功能,包括车位租赁、停车费用计算和缴纳,以及停车场运营数据的统计和分析等功能。 4. Configuration模块:该模块实现了停车场的基础配置和参数管理功能,包括车位数量、收费标准和系统设置等功能。 5. Common模块:该模块包含了一些公共的模型和工具类,用于提供系统级别的服务和支持。 通过这个实战项目的源码学习,可以深入了解WPF Prism框架的应用及其MVVM架构和依赖注入的设计思想,也可以了解如何实现一个完整的智能化停车场管理系统。同时,该项目源码可以作为一个参考,通过在此基础上进行二次开发和定制,实现更加具体化的应用需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值