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详解--第七篇 拓展模块(译)的更多相关文章

  1. Orchard详解--第八篇 拓展模块及引用的预处理

    从上一篇可以看出Orchard在处理拓展模块时主要有两个组件,一个是Folder另一个是Loader,前者用于搜索后者用于加载. 其中Folder一共有三个:Module Folder.Core Fo ...

  2. Orchard详解--第三篇 依赖注入之基础设施

    Orchard提供了依赖注入机制,并且框架的实现也离不开依赖注入如模块管理.日志.事件等.在前一篇中提到在Global.asax中定义的HostInitialization创建了Autofac的IoC ...

  3. Orchard详解--第六篇 CacheManager 2

    接上一篇,关于ICacheContextAccessor先看一下默认实现,用于保存一个获取上下文,且这个上下文是线程静态的: public class DefaultCacheContextAcces ...

  4. Orchard详解--第五篇 CacheManager

    上一篇文章介绍了Orchard中的缓存,本篇主要针对CacheManager进行分析,CacheManager在Orchard中用于存储应用程序的配置信息以及框架内部的一些功能支持,包括整个拓展及拓展 ...

  5. Orchard详解--第四篇 缓存介绍

    Orchard提供了多级缓存支持,它们分别是: 1. 应用程序配置级缓存ICacheManager: 它用来存储应用程序的配置信息并且可以提供一组可扩展的参数来处理缓存过期问题,在Orchard中默认 ...

  6. PE文件格式详解(七)

    PE文件格式详解(七)   Ox00 前言 前面好几篇在讲输入表,今天要讲的是输出表和地址的是地址重定位.有了前面的基础,其实对于怎么找输出表地址重定位的表已经非常熟悉了.   0x01 输出表结构 ...

  7. IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构(转载)

    IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构 系列文章链接: IIS负载均衡-Application Request Route详解第一篇: ...

  8. [转]ANDROID L——Material Design详解(动画篇)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...

  9. appledoc导出iOS代码文档的使用和问题详解(干货篇)

    appledoc导出iOS代码文档的使用和问题详解(干货篇) 1. 简单说一下背景和自己感受 背景: 项目好像突然黄了,公司让详细写项目代码的注释并且导出文档,弄完之后就要封版. 说实话:听到这个消息 ...

随机推荐

  1. MySQL批量插入数据的几种方法

    最近公司要求测试数据库的性能,就上网查了一些批量插入数据的代码,发现有好几种不同的用法,插入同样数据的耗时也有区别 别的先不说,先上一段代码与君共享 方法一: package com.bigdata; ...

  2. Cookie登录保存

    Login.aspx <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Log ...

  3. Java中的instanceof和isInstance基础讲解

    1. instanceof 是一个操作符 使用方法: ? 1 2 if(a instanceof B){ } 表示:a 是不是 B 这种类型 2. isInstance是Class类的一个方法 ? 1 ...

  4. Ajax的初级使用

    一.AJAX简介(本文的例子都使用的是原生的ajax) 老技术新用法二.异步和同步区别三.XMLHttpRequest对象(面试题) 属性: readyState: 0:未初始化 1:open方法已经 ...

  5. Updatepanel 后端返回后,在 Updatepanel 内控件的前端 js 失效问题

    实际情况:点击下箭头弹出列表,点击列表上的隐藏按钮隐藏列表. 背景:模块没有使用Js或者Jquery的Ajax功能,而是使用Asp.Net的Ajax控件--UpdatePanel + ScriptMa ...

  6. petapoco 实体中字段去掉关联(类似于EF中的NotMap)

    怎么才能让不是数据库表中的字段放在实体中而不影响正常的插入和更新呢? 找到 PetaPoco.cs 文件,打开之后,搜索插入方法(Insert),然后继续找到下一层方法 就能看到如下代码: 看到这个注 ...

  7. [android] 获取系统的联系人信息

    内容提供是实质上是个接口,后门,他给别人提供数据,系统联系人是个比较复杂的内容通过者. 找到/data/data/com.android.providers.contacts/contacts2.db ...

  8. Xhprof graphviz Warning: proc_open() [function.proc-open]: CreateProcess failed, error code 解决方法

    Xhprof在windows下点击[View Full Callgraph]调用graphviz软件时.警告Warning: proc_open() [function.proc-open]: Cre ...

  9. Java学习笔记之——this关键字、非静态成员属性和静态成员属性的区别、类的加载顺序

    一.this关键字 1.代表当前类的对象 2.通过” . ”调用成员属性和成员方法 3.通过this可以区分成员属性和参数 参数名和属性名相同的情况,默认是参数名 二.非静态成员属性和静态成员属性的区 ...

  10. 【转】消除代码中的 if-else/switch-case

    在很多时候,我们代码中会有很多分支,而且分支下面的代码又有一些复杂的逻辑,相信很多人都喜欢用 if-else/switch-case 去实现.做的不好的会直接把实现的代码放在 if-else/swit ...