惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
Jina AI
Jina AI
博客园_首页
J
Java Code Geeks
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
Forbes - Security
Forbes - Security
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
The Register - Security
The Register - Security
N
News | PayPal Newsroom
S
Security Archives - TechRepublic
量子位
Cisco Talos Blog
Cisco Talos Blog
V
V2EX
C
Cisco Blogs
The Cloudflare Blog
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
Scott Helme
Scott Helme
S
Securelist
Security Latest
Security Latest
爱范儿
爱范儿
TaoSecurity Blog
TaoSecurity Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
L
LINUX DO - 最新话题
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
美团技术团队
Know Your Adversary
Know Your Adversary
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
PCI Perspectives
PCI Perspectives
月光博客
月光博客
T
Tailwind CSS Blog
Cloudbric
Cloudbric
小众软件
小众软件
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
K
Kaspersky official blog
D
DataBreaches.Net
博客园 - 【当耐特】
有赞技术团队
有赞技术团队

博客园 - 二十四画生

Orchard 1.3新功能之——规则(Rules) Orchard 1.3新功能之——Markdown编辑器 Orchard 1.3 发布了! Orchard中的计划任务功能(Schedule) Orchard网站App_Data目录里的文件介绍 在Orchard中使用样式及脚本 Orchard中的多站点功能(Multi-Tenant) Orchard中的多语言功能 Orchard中的列表功能 Orchard中的用户、角色及权限 自定义Orchard站点辅助工具——Shape Tracing Orchard中的形状候补(Alternates) Orchard是如何呈现内容的 理解Orchard中的placement.info文件 详解Orchard主题(Theme) 在Orchard中创建一个自定义字段类型 在Orchard中为命令行工具(Command-Line)添加一个新命令 在Orchard中处理一对多关系 在Orchard中创建一个主题(Theme)
Orchard动态编译机制
二十四画生 · 2011-07-27 · via 博客园 - 二十四画生

Posted on 2011-07-27 11:46  二十四画生  阅读(7406)  评论()    收藏  举报

Orchard作为一个可扩展的CMS系统,需要在运行时加载一些模块或主题(统称扩展)。从Orchard 0.5版起就致力于让安装和升级这些扩展变得更加简单。Orchard和其他任何一个ASP.NET MVC应用程序一样,都可以在Visual Studio环境下编译。但是Orchard还提供了另外一种模块加载策略,例如,它允许模块的dll无需部署在网站的bin目录下。此外Orchard还可以动态的根据模块源代码来编译模块。这样可以比较灵活的部署dll文件,并且可支持在没有Visual Studio环境的情况下随时编译所修改的模块源代码。这有点类似于ASP.NET的“App_Code”文件夹,只不过Orchard支持更多的这样的文件夹。本文将从技术层面上描述Orchard是如何加载模块并动态编译的。

概述

Orchard应用程序启动时,Orchard框架(具体由ExtensionLoaderCoordinator类负责)需要明白安装了那些模块并激活他们(就是加载这些模块的dll)。更细化的来说这个过程分为三个阶段:

1、发现:搞清楚目前网站都有哪些模块。

2、激活:搞清楚用什么策略来激活或加载每一个模块。

3、引用解析:搞清楚激活这些模块都需要引用那些程序集。这个阶段技术属于“激活”阶段的一部分,但它作为一个单独的部分更容易去思考关于引用解析的问题。

一旦模块被正取激活,它们将在进一步检查去检测并启用个别的功能,不过这个就不是本文需要讨论的主题了。

发现

列出Orchard中可用的模块是通过查询一些文件夹下面的“module.txt”文件获得的。下面将分别列举这些默认查询的文件夹:

"~/Modules" 文件夹

"~/Modules" 文件夹包含了大多数Orchard模块。Orchard约定每一个模块存储在一个名为<ModuleName>的子文件夹中,并且需要包含一个“module.txt”文件。打包、发布和分析模块只此次文件夹下的模块。这个文件夹就是用户自定义扩展Orchard模块的文件夹。

"~/Core"文件夹

"~/Core"文件夹包含一些Orchard中最核心的模块,这些模块有Orchard团队提供。用户通常不在这里添加新的模块。

"~/Themes"文件夹

"~/Themes"文件夹包含了Orchard主题。作为动态编译,主题几乎被当作模块一样处理,处理主题没有代码(bin 和 .csproj文件)。本文的其余部分,当我们提到“模块”时,他同样也适用于“主题”。

注:”~/”表示网站根目录。

示例

下面是一个Orchard安装实例,其中包含6个扩展:两个核心模块“Common”和“Localization”,两个应用模块“Foo”和“Bar”,还有两个主题“T1”和“T2”。

RootFolder
  Core
    Common
      module.txt  <= "Common" module from "Core"
    Localization
      module.txt  <= "Localization" module from "Core"
  Modules
    Foo
      module.txt  <= "Foo" module
    Bar
      module.txt  <= "Bar" module
  Themes
    T2
      theme.txt  <= "T1" theme
    T2
      theme.txt  <= "T2" theme

激活

一旦Orchard从发现阶段收集了所有的“module.txt”文件,Orchard将使用不同的策略(或“模块装载机”)在内存中加载这些模块。在内部,加载模块的行为,是一种活动。作为输入“module.txt”文件并返回一个“System.Type”列表。请注意,这有别于返回一个“System.Assembly”列表,因为Orchard支持一个程序集包含多个模块,如:“Orchard.Core.dll”就包含了约10个Orchard模块。Orchard目前实现了以下模块加载策略(装载机):

“已引用模块”装载机

这个装载机在“~/bin”目录中查找“module.txt”文件中模块名对应的程序集,如果这个程序集存在,它将加载并返回改程序集的所有类型。这种加载机用于当所有模块都是预先编译好的,并且其dll都存储在“~/bin”目录中的情况,这是一种典型“asp.net mvc”应用程序方式。

“核心模块”装载机

如果“module.txt”文件来自于"~/Core"文件夹,核心模块装载机将返回来自于Orchard.Core.dll中,"Orchard.Core.<moduleMame>"命名空间下的所有类型。Orchard.Core.dll是一个特殊的程序集,它包含了Orchard核心模块,在Orchard框架基础上提供一些基本功能。

“预编译模块”装载机

如果“module.txt”文件来自于"~/Modules" 文件夹,预编译模块装载机将在“~/Modules/<ModuleName>/bin”中查找名为<moduleMame>的程序集。如果这个文件存在,它将被复制到"~/App_Data/Dependencies"文件夹下,这是一个特殊的文件夹,是用于ASP.net查找“~/bin”文件夹以外程序集的地方。

“动态模块”装载机

如果“module.txt”文件来自于"~/Modules" 文件夹,动态模块装载机将在“~/Modules/<ModuleName>/bin”中查找.csproj文件。如果这个文件存在,这个装载机将使用Orchard编译管理器根据.csproj文件来编译程序集并返回改程序集的所有类型。

注:这个装载机在系统执行的时候只有一个,常常被称为“动态编译”。事实上这是可以选择的,如果所有模块都是预编译好的,也可以选择其他的装载机。

装载机选择

既然可能有不止一个装载机能够加载一个指定的模块,Orchard是如何做到选择正确的呢?每个装载机都可以返回一个相应模块的 “最后修改时间”,对于存在多个装载机时,Orhcard根据最新的“最后修改时间”来决定使用何种装载机。例如:一个模块包含所有的源文件包括.csporj文件和已经编译到bin目录中的dll。第一次加载模块的时候,Orchard会在bin目录中加载程序集,应为源代码比程序集新的情况会比较少。然而,如果源代码有了任何改变后,动态模块装载机返回的“最后修改时间”大于在bin目录中加载程序集的“最后修改时间”,Orchard将采用动态模块装载机。值得注意的是这种分歧只存在于"~/Modules" 文件夹下的模块,因为"~/Core"文件夹下的模块只会采用核心模块装载机。

示例

RootFolder
  Bin
    Orchard.Web.dll
    Orchard.Core.dll
    Foo.dll
  Core           
    Common        <= "Core Module" loader
      module.txt
    Localization  <= "Core Module" loader
      module.txt
  Modules
    Foo           <= "Reference Module" loader (because a "~/bin/Foo.dll" file exists)
      module.txt
    Bar           <= "Precompiled Module" loader (because a "~/Modules/Bar/bin/Bar.dll" file exists)
      bin
        Bar.dll
      module.txt
    Baz           <= "Dynamic Module" loader (because a "~/Modules/Baz/Baz.csproj" file exists)
      Controller
         BazControler.cs
      Baz.csproj
      module.txt

引用解析

动态模块加载机将根据.csproj文件中References节点的内容在模块的Bin目录中查找模块所引用的其他程序集文件,并将其复制到"~/App_Data/Dependencies"文件夹下。注意模块所引用的其他dll需要复制到模块Bin目录下,并起引用位置也要在此目录中。

配置更改检测

正如上文所述,在应用程序启动时加载模块。然而,一旦应用程序启动,改变依然可能随时发生,如:一个模块的源代码可能手动更新,一个模块可能会在网站上安装或删除等。来检测这些变化,就需要Orchard提供一个“监视”潜在变化的机制并在发生变化是通知模块装载器。当检测到变化时,当前模块的配置将被丢弃并且将同时重新审查、加载和激活模块,就像应用程序重新启动一样。在某些情况下,这些变化需要一个ASP.net的AppDomain重新启动(如:一个新版本模块的程序集需要被加载),Orchard将检测这样的情况并让一个ASP.net AppDomain重新启动。

"~/App_Data/Dependencies/Dependencies.xml" 文件

这个文件包含了最后一次成功加载应用程序时的模块、装载机和模块所引用的程序集列表。查看这个文件的内容,可以用于调试,检测相应的dll是否被加载。 

参考文档

http://www.orchardproject.net/docs/Orchard-module-loader-and-dynamic-compilation.ashx