模块概述

谈到模块大家应该都不会感到陌生,不管是前端还是后端都有模块的概念,XAF中的模块概念与大多数框架中的模块概念是相通的。XAF模块首先是一个.NET类库,同时它还包含一个继承自ModuleBase的Module类,Module类主要用于收集及对外暴露模块中的一些资源(BusinessObject、Controller、Action、Model、PropertyEditort等),同时XAF模块间的依赖与.NET类库间的依赖也是一致的,比如:A模块依赖B模块,B模块依赖C模块,那A模块同时拥有了B模块与C模块所提供的资源。XAF模块涵盖的功能很多,当前只对模块的部分功能进行介绍,后续还会与其它的概念一起介绍。

XAF默认提供了大量的基础功能模块(审计、图表、仪表盘、验证、报表、状态机等),你可以根据需要将这些模块添加到你的项目中。

项目结构

XAF项目主要包含应用程序项目与模块项目,当然也可以包含普通的.NET项目。应用程序项目是负责项目的启动,所以它需要指定平台(WinForm与Blazor),模块项目在不依赖特定平台时,是可以被其它应用程序项目或其它模块项目引用,依赖特定平台后,只能被特定平台的项目引用。

在XAF22.1之前的版本中,XAF项目中包含两种模块项目类型,一种是与平台相关的,一种是不相关的,在之后的版本中,将平台相关的模块代码移到了应用程序项目中,目的是为了简化项目结构。如果你想创建独立的模块,并且模块中包含了不同平台的代码,你还是需要创建平台相关的模块项目。

模块注册

模块注册分为两种,一种是模块间依赖的注册,一种是将模块注册到应用程序项目中,这两种注册方式是不一样的。

在整个XAF项目启动过程中模块是最先被初始化的,这里要引出一个概念Application(在不同的平台会有不同的实现,它们都是XafApplication的子类),从名字你就可以看出它在XAF中的地位,它上面挂载了运行XAF所需的所有资源,XAF模块当然也在其中,同时它还提供了丰富的功能,在WinForm项目中Application是以单例形式存在的,在Blazor项目中每一个会话都会有一个Application实例,现在你可以简单将Application理解为整个XAF应用的中心,后面会对它进行单独的介绍。

模块注册到应用程序项目中

在XAF22.1后,将模块注册到应用程序项目中WinForm与Blazor采用了相同的配置方式,下面以WinForm为例

上面的代码是ApplicationBuilder类中的片段,在XAF22.1后,WinForm项目都会存在一个ApplicationBuilder类,它是用于构建Application实例。接触过XAF的小伙伴对上面的代码应该比较容易理解,这里简单的解读一下,builder是IXafApplicationBuilder<TBuilder>的一个实例,在不同的平台(WinForm与Blazor)会有不同的实现。

builder.Modules是专门用于将模块注册到应用程序项目中的,它上有一个Add方法可以方便对模块进行注册,当然你也可以基于Add方法再作进一步的封装,例如:AddConditionalAppearance(ConditionalAppearance模块的注册方法),注册模块的先后顺序并不影响模块的加载。

在之前的XAF版本中,将模块注册到应用程序项目中,都是将模块中Module类的实例添加到Application.Modules中,新的注册方式可读性更强,目的是相同的,但将模块添加到Application.Modules中是在builder.Build()时执行的。

builder实例中包含一个_buildSteps委托集合,调用builder上的方法也就是向_buildSteps集合中添加委托(Action<XafApplication>),委托有一个Application参数,借用此参数可以对Application进行配置,最后的builder.Build()是将_buildSteps集合中的委托遍历并执行,并返回Application的一个实例。下面是Build方法简化后的代码

在模块注册到应用程序项目中时可以对模块进行配置,如果是自己的模块,首先需要在模块的Module类中添加对应的属性,如Test,在注册时直接给模块属性赋值,如下面的代码。如何使用模块Module类中的属性,将在后面进行介绍

如果你的模块是对外发布的,想更严谨一些,你可以参考XAF内部模块的做法,单独创建一个Options类,通过Options类收集模块配置,避免使用者直接给Module类中的属性赋值

模块间依赖的注册

在前面的介绍中,大家应该已经知道模块的依赖与.NET类库的依赖是相似的。一个XAF模块想依赖另一个XAF模块,首先要引用这个被依赖模块的类库,并在Module类的构造函数中,将被依赖模块中Module类的类型添加到RequiredModuleTypes中,代码如下:

由于RequiredModuleTypes的初始值是来自GetRequiredModuleTypesCore方法,所以我们也可以在Module类中重写GetRequiredModuleTypesCore方法来实现相同的操作,代码如下:

在上面的代码中,模块注册的先后顺序是不影响后续操作的,甚至依赖模块被无意中重复添加了,也不会有任何影响,因为模块在被正式加载时,会进行相应的过滤,当然最好不要这样做,下面的代码是可以正常运行的

模块加载

模块加载是在builder.Build()时进行的,模块加载的核心逻辑是放在ModuleList类中的。

这里简单说一下它的加载逻辑,ModuleList会先加载通过builder在应用程序项目中注册的模块,然后再去加载已加载模块的依赖模块,依赖模块再去加载自身的依赖模块,这里是一个递归,当然在加载过程中ModuleList会判断如果已被加载则跳过,最终会保证ModuleList中每一个模块类型只有一个模块实例,这里的ModuleList就是Application.Modules,你可以通过Application.Modules获取被加载的所有模块实例。

ModuleList类上有一个FindModule方法,可以使用它通过模块类型查找模块实例,那我们就可以在能够访问到Application的情况下,调用Application.Modules.FindModule查找模块实例,就可以访问到模块中的属性。

总结

模块在XAF中是一个比较重要的概念,模块中还很多知识点,这里只介绍了模块的注册与加载,在后续还会结合其它概念再介绍,同时还要注意在XAF22.1后,XAF项目结构进行了简化,同时模块在应用程序项目中的注册方式也不一样了。

注意:本系列文章只是讲解XAF中常用到的概念,方便大家理解,具体的操作方法还是需要参考官方文档

XAF新手入门 - 模块(Module)的更多相关文章

  1. XAF新手入门 - 前言

    很多小伙伴在第一次接触XAF时,会被它的丰富功能及开箱即用的特点所吸引,即使在不了解XAF的情况下,也能够依葫芦画瓢创建一个功能丰富的应用,但当应用到实际项目中时,你会发现与之前的愿景差距很大,很多都 ...

  2. python2.7入门---模块(Module)

        来,这次我们就看下Python 模块(Module).它是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句.模块让你能够有逻辑地组织你的 Pytho ...

  3. XAF新手入门 - 类型子系统(Types Info Subsystem)

    类型子系统概述 类型子系统是XAF的核心概念,但我们平时却很少关注它,它集中存储了模块中的类型,它是生成应用程序模型(Application Model)的基础,它与XAF中其它的概念都有所关联,了解 ...

  4. 新手入门指导:Vue 2.0 的建议学习顺序

    起步 1. 扎实的 JavaScript / HTML / CSS 基本功.这是前置条件. 2. 通读官方教程 (guide) 的基础篇.不要用任何构建工具,就只用最简单的 <script> ...

  5. 课程上线 -“新手入门 : Windows Phone 8.1 开发”

    经过近1个月的准备和录制,“新手入门 : Windows Phone 8.1 开发”系列课程已经在Microsoft 虚拟学院上线,链接地址为:http://www.microsoftvirtuala ...

  6. discuz插件开发新手入门 超详细

    作为一个新手,目前也是刚刚玩转discuz的插件功能,好东西不敢独享,就拿出来大家一起分享入门的过程.现在网上很多关于discuz的插件教程都是很简单的教程,原因可能是这个东西是商业化的东西,本着分享 ...

  7. discuz 插件开发 新手入门

    作为一个新手,目前也是刚刚玩转discuz的插件功能,好东西不敢独享,就拿出来大家一起分享入门的过程.现在网上很多关于discuz的插件教程都是很简单的教程,原因可能是这个东西是商业化的东西,本着分享 ...

  8. Xorboot-UEFI新手入门教程

    Xorboot-UEFI新手入门教程        Xorboot-UEFI是一款UEFI下轻量级的图形化多系统引导程序,pauly于2014年国庆节期间发布了预览版.搜了下论坛,关于Xorboot- ...

  9. 即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?

    本文引用了“蔷薇Nina”的“Nginx 相关介绍(Nginx是什么?能干嘛?)”一文部分内容,感谢作者的无私分享. 1.引言   Nginx(及其衍生产品)是目前被大量使用的服务端反向代理和负载均衡 ...

随机推荐

  1. mybatis 07: sql标签中 "#{}" 和 "${}" 的作用和比较

    "#{}"占位符 作用 传参大部分使用"#{}",在数据库底层使用的是:PreparedStatement预编译处理对象 数据库底层被解析为"?&qu ...

  2. Host long.com not found: 2(SERVFAIL)

    环境: centos  7.9 地址:192.168.200.100 相关配置 name.conf文件: named.zones文件: 正反解析文件: 重启DNS服务: 1 [root@server ...

  3. from表单、css选择器、css组合器、字体样式、背景属性、边框设置、display设置

    目录 一.form表单 1.form表单功能 2.表单使用原理 二.前端基础之css 1.关于css的介绍 2.css语法 3.三种编写CSS的方式 3.1.style内部直接编写css代码 3.2. ...

  4. 解决:Uncaught TypeError: $ is not a function

    本来好好的,突然就出现的错误,不过这并不是什么难解决的错误: 我的问题是:在js文件里我定义了一个var $;变量,只要把这个去掉就没问题了. 出现这种错误的解决方法: 1,先看看你的jq文件是否已经 ...

  5. 二叉搜索树TREE(线段树,区间DP)

    前言 线段树+区间DP题,线段树却不是优化DP的,是不是很意外? 题面 二叉搜索树是一种二叉树,每个节点都有一个权值,并且一个点的权值比其左子树里的点权值都大,比起右子树里的点权值都小. 一种朴素的向 ...

  6. KingbaseES 自增列三种方式

    KingbaseES中3种自增长类型sequence,serial,identity的区别: 对象 显示插入 显示插入后更新最大值 清空表后是否重置 是否跟事务一起回滚 多对象共享 支持重置 出现错误 ...

  7. 【读书笔记】C#高级编程 第二十章 诊断

    (一)诊断概述 名称空间System.Diagnostics提供了用于跟踪.事件日志.性能测量以及代码协定的类.System.Diagnostics.Contracts名称空间中的类可以定义前提条件. ...

  8. python中使用数组作为索引

    链接:https://blog.csdn.net/yzlh2009/article/details/114118470 情况一,索引数组为整数值 情况二,索引数组为bool值

  9. Windows Admin Center无法访问

    近日,有一台安装了Windows Admin Center的服务器无法访问了.遇到错误ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY.本以为这是更新了Chromium内 ...

  10. 我的Vue之旅、02 ES6基础、模块、路径、IO

    自定义模块 为什么要模块?模块化源代码能给我们带来什么好处? 试想一个巨无霸网购平台,在没有模块化的情况下,如果出现bug,程序员就要在几百万行代码里调试,导致后期维护成本上升,为了解决问题,模块化按 ...