Orchard作为一个组件化的CMS,它能够在运行时加载任意模块。
Orchard和其它ASP.NET MVC应用一样,支持通过Visual Studio来加载已经编译为程序集的模块,且它还提供了自定义的模块加载策略,如允许加载没有部署到"~/bin"目录下的程序集模块。
另外,Orchard还支持直接部署源代码然后动态编译的功能,这个功能比这届部署二进制文件更灵活,而且还可以在一些适合的地方在不使用Visual Studio的情况下自定义代码,类似与ASP.NET的App_Code目录,但是Orchard支持多个独立的目录(一个模块一个)。
本章的目的是在技术层次描述Orchard如何加载模块,这个功能经常被认为是Orchard的动态编译,即使动态编译技术仅用于非常特殊的场景。
概述
当Orchard应用程序启动时,Orchard框架(确切的将是ExtensionloaderCoordinator)计算出那些模块被安装并激活它们(加载相应程序集)。
在顶层看来,这个过程主要有三个步骤:
- 查找:找出这个网站有那些模块。
- 激活:找出使用什么策略来加载这些模块。
- 解决引用依赖:找出哪些引用程序集用于激活模块。这个是激活部分,但是需要在这里就考虑如何处理模块的依赖问题。
搜索
Orchard通过搜索不同目录下的"module.txt"和"theme.txt"文件来获取到一个可用的拓展列表。这些目录主要有:
"~/Modules"目录
该目录下面包含了大量的Orchard模块,并约定每一个模块存放在一个以模块名称命名的子目录下,每一个目录下有一个"module.txt"文件,这个目录仅支持模块的打包、分配和共享。
"~/Core"目录
这个目录包含了一个"Orchard.Core"的程序集,该程序集中包含的模块是Orchard系统中的核心部分,这些模块不能像"~/Modules"目录下的模块那样自由修改。
"~/Themes"目录
这个目录下面包含了Orchard主题,关于动态编译,主题和模块基本类似,除了主题不需要代码。
自定义目录
在Orchard1.10版本中提供了新的功能,允许从自定义的目录下加载拓展模块。自定义的目录可以在AppSetting中配置。
例子
下面这个例子中Common和Localization是Core模块,Orchard.Azure和Orchard.Caching是内置的模块,SafeMode和TheAdmin是内置主题,MyModule1和MyModule2是自定义路径中的自定义模块,MyBase和MyTheme是自定义主题目录下的自定义主题。
激活
当Orchard收集到所有的"Module.txt"后,Orchard将使用不同策略来将这些模块加载到内存中。在程序内部,"加载模块"这个动作是一个以"module.txt"文件作为输入然后将一个类型为"System.Type"的列表作为输出的操作。这将比简单的返回一个"System.Assembly"更通用,这样Orchard可以支持在一个程序集中包含多个模块,如Orchard.Core.dll中包含了大约10个模块。
"引用模块"加载器
这个加载器查找"~/bin"目录下的和"module.txt"文件中指定模块名称一致的程序集,如果这个程序集存在,那么将这个模块加载然后返回它所有的类型。这个加载器用于通过"ASP.NET的方式"加载一些已经预编译好在"~/bin"目录下的程序集(注:这里一般是因为Orchard的根程序引用了其中某一些模块,以致于根程序编译时会将该程序集放置到~/bin目录下,这种情况ASP.NET就会自动加载该程序集,而加载器的功能主要用于获取该程序集的所有类型)。
"核心模块"加载器
如果"module.txt"文件是从"~/Core"目录下来的,那么CoreExtensionLoader将从Orchard.Core程序集的"Orchard.Core.<模块名称>"的命名空间下返回所有类型。Orchard.Core包含多个被称为核心的模块,它们在Orchard Framework上提供了一些基础功能。
"预编译模块"加载器
如果"module.txt"来自"~/Modules"目录,那么该加载器就会到"~/Modules/<ModuleName>/bin"目录下根据模块名称查找程序集文件,如果存在,那么将它复制到"~/App_Data/Dependencies"目录下,这个目录是一个特殊的目录,它用于ASP.NET应用程序在"~/bin"目录之外查找附加的程序集。
"动态模块"加载器
如果"module.txt"来自"~/Modules"目录,且在"~/Modules/<ModuleName>"目录下存在".csproj"文件,那么该加载器就会使用Orchard build manager编译这个.csproj文件,并返回该程序集的所有类型。
注:该加载器是Orchard中唯一一个使用"动态编译"的加载器,而且如果该模块已经预编译,那么它是可选的。
加载器二义性处理
因为有可能出现一个给定模块被多个加载器加载,所以Orchard有一个处理歧义的方法,如选择"正确的"加载器。每一个加载器在加载模块时都能够返回一个模块"最新修改时间"。对于一个给定模块,如果存在多个加载器,那么Orchard将选择返回的"最新修改时间"最近的加载器。
例如,一个给定模块即存在包含.csproj文件的源代码且bin目录下也存在编译好的程序集。模块的第一次加载,Orchard会加载"bin"目录下的程序集,虽然可能这个程序集不是最新的(代码编译后,代码被修改)。但是对于Orchard来说如果代码在编译后产生任何的修改,"动态模块"加载器将返回一个文件最近的修改时间(代码或csproj文件),然后Orchard将根据时间来选择正确的加载器(预编译加载器还是动态编译加载器)。
需要注意的是对于Core模块来说,它只有一种加载方式,所以不会出现二义性。
例子
禁用"动态模块"加载器
在生产环境应该禁用动态加载,因为生成环境不应该动态的安装、加载模块,而另一些原因是因为动态加载会创建很多FileSystemWatcher(影响性能)来检测模块变化。
禁用该加载器需要在HostComponents.config文件中加入以下内容:
然后部署该文件并重启应用池。
注:你必须检查每一个模块的bin目录是否已经存在编译后的程序集。
配置的变化检测
正如上面介绍的,Orchard应用程序在启动时将加载相关模块。然而一旦应用程序启动,可能会发生变化,如:可能安装新模块、手动改变源代码、删除模块等等。为了检测这些改变,Orchard让每一个加载器监控变化然后在发生变化时发送通知。
当变化被检测到,当前模块的配置将被废弃然后在应用程序再一次启动时重新验证、加载、激活模块。一些情况下,这些改变需要ASP.NET应用域重启(如新版本程序集的加载)。Orchard监听这些情况并强制重启ASP.NET应用程序域。
~/App_Data/Dependencies/Dependencies.xml文件
这个文件包含了模块的列表、这些模块的加载器和模块最后一次正确的引用配置,它是Orchard最后一次运行成功的所有模块的配置信息。它可以用于检查新版本模块是否被加载等等。
原文:
翻译这篇文档的原因是,它详细的对Orchard拓展模块加载内容进行了介绍,而接下来将从代码层面分析以上内容是如何实现的。
- Orchard详解--第八篇 拓展模块及引用的预处理
从上一篇可以看出Orchard在处理拓展模块时主要有两个组件,一个是Folder另一个是Loader,前者用于搜索后者用于加载. 其中Folder一共有三个:Module Folder.Core Fo ...
- Orchard详解--第三篇 依赖注入之基础设施
Orchard提供了依赖注入机制,并且框架的实现也离不开依赖注入如模块管理.日志.事件等.在前一篇中提到在Global.asax中定义的HostInitialization创建了Autofac的IoC ...
- Orchard详解--第六篇 CacheManager 2
接上一篇,关于ICacheContextAccessor先看一下默认实现,用于保存一个获取上下文,且这个上下文是线程静态的: public class DefaultCacheContextAcces ...
- Orchard详解--第五篇 CacheManager
上一篇文章介绍了Orchard中的缓存,本篇主要针对CacheManager进行分析,CacheManager在Orchard中用于存储应用程序的配置信息以及框架内部的一些功能支持,包括整个拓展及拓展 ...
- Orchard详解--第四篇 缓存介绍
Orchard提供了多级缓存支持,它们分别是: 1. 应用程序配置级缓存ICacheManager: 它用来存储应用程序的配置信息并且可以提供一组可扩展的参数来处理缓存过期问题,在Orchard中默认 ...
- PE文件格式详解(七)
PE文件格式详解(七) Ox00 前言 前面好几篇在讲输入表,今天要讲的是输出表和地址的是地址重定位.有了前面的基础,其实对于怎么找输出表地址重定位的表已经非常熟悉了. 0x01 输出表结构 ...
- IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构(转载)
IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构 系列文章链接: IIS负载均衡-Application Request Route详解第一篇: ...
- [转]ANDROID L——Material Design详解(动画篇)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...
- appledoc导出iOS代码文档的使用和问题详解(干货篇)
appledoc导出iOS代码文档的使用和问题详解(干货篇) 1. 简单说一下背景和自己感受 背景: 项目好像突然黄了,公司让详细写项目代码的注释并且导出文档,弄完之后就要封版. 说实话:听到这个消息 ...
随机推荐
- sql server 备份与恢复系列五 完整模式下的备份与还原
一.概述 前面介绍了简单恢复模式和大容量恢复模式,这篇继续写完整恢复模式下的备份与还原.在完整恢复模式里最大的优点是只要能成功备份尾日志,就可以还原到日志备份内包含的任何时点("时点恢复&q ...
- 对requestAnimationFrame的一点理解
假设一个web页面为60fps(fps意为frame per second),这意为着这个页面每秒钟能重新渲染60次,60帧/1000ms换算过来约为16.6ms/帧. requestAnimatio ...
- 编写高质量代码改善java程序的151个建议——[110-117]异常及Web项目中异常处理
原创地址:http://www.cnblogs.com/Alandre/(泥沙砖瓦浆木匠),需要转载的,保留下! 文章宗旨:Talk is cheap show me the code. 大成若缺,其 ...
- java如何获取一个double的小数位数
前言 看标题是不是觉得这是一个很简单的问题,我一开始也是这么认为的,但是实际情况下,在各种情况下我们都进行了测试,发现很多实际情况是无法不尽如人意的. 方法分析 当前能想到的比较容易有下面几种 1.直 ...
- JavaScript和Ajax部分(5)
41. jQuery中的load方法一般怎么用的? 答:load方法一般在 载入远程HTML 代码并插入到DOM中的时候用通常用来从Web服务器上获取静态的数据文件. 如果要传递参数的话,可以使用$. ...
- (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)
在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机 前提:服务器端安装桌面版的centos系统 CentOS Linux release 7.5.1804 (Core) ...
- mysql常用字符串操作函数大全,以及实例
今天在论坛中看到一个关于mysql的问题,问题如下 good_id cat_id12654 665,56912655 601,4722 goods_id是商品i ...
- Java——代码块
前言 在程序编写之中可以直接使用{...}定义的一段语句就是代码块.根据代码块的位置以及关键字的不同可以分为4种:普通代码块.构造块.静态块以及同步代码块(多线程相关).下面将先介绍前3种以及Java ...
- 第3章 Linux上文件的权限管理
3.1 文件/目录的权限 3.1.1 文件的权限 每个文件都有其所有者(u:user).所属组(g:group)和其他人(o:other)对它的操作权限,a:all则同时代表这3者.权限包括读(r:r ...
- 关于VUE首屏加载过长的优化,VUE项目开发优化
1. 按需引入UI组件 当下市面上流行的UI组件基本都支持按需加载,本文以Element UI为例: (1) 新建一个elementUI.js文件 (2) 访问地址找到按需引入方式的说 ...