九、其它话题(一) Orchard Dynamic Compilation

Introduction

做为可组装的CMS,Orchard能在运行时装载一组随意的模块.

Orchard像任何ASP.NET MVC程序一样,支持使用VS将模块编译成程序集,Orchard也提供一个定制模块装载策略,例如:允许装载关于模块的程序集(不用部署到bin文件夹).

除此之外,Orchard支持仅部署源代码的模块的动态编译,这比部署二进制文件更具灵活性,使一些有趣的场景,如”in place"不用使用VS进行代码定制,这有点像ASP.NET App_Code目录,除了Orchard独立地支持多”logical folder”(通常每个模块一个).

 

High Level Overview

当Orchard程序启动,Orchard框架需计算出网站中安装了哪些模块和激活了它们(通常装载它们的程序集).

在高层,这个过程能划分成3个独立阶段:

  • Discovery: 计算出网站中出现了哪些模块
  • Activation:计算出什么策略用来激活(或装载)每一个模块
  • References Resolution: 计算出每个模块需要被激活的程序集引用是哪些,这个阶段是"activation"阶段的技术部分,但它更容易思考作为分离的部分引用 解决方案的问题

Discovery

Orchard安装的可用模块列表是通过搜索一些目录中的module.txt文件建立的,默认搜索下面列出的目录:

"~/Modules" folder

Modules目录的目的是包含大多数Orchard模块,约定是每个模块在以模块名称命名的子目录中存储,并包含一个module.txt文件,打包,发布,分享模块仅支持Modules目录中的模块.

"~/Core" Folder

Core文件夹包含了定义在Orchard.Core程序集中的模块,这些模块是Orchard系统核心的一部分,并不能像Modules目录中的模块一样被随意地修改.

"~/Themes" Folder

Themes包含了Orchard的主题,关于动态编译,主题几乎完全被视为模块,除了主题没有代码(bin中的程序集或.csproj文件),本页面的其余部分,当提到模块,应该明白这个概念适用于主题.

Example

这是Orchard安装的例子,包含了6个模块:Common,Localization,Foo,Bar

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

 

Activation

每次Orchard从发现阶段收集所有的Module.txt文件,Orchard使用完全分开的策略(或叫Module loaders)装载这些模块到内存中,本质地,装载一个模块的行为是用一个module.txt文件做为输入返回一个System.Type列表做为输出的活动,注意这是比简单地返回System.Assembly稍微通用的,如它允许Orchard支持每个程序集的多模块。例如:Orchard.Core.dll程序集当前包含了大约10个模块

Orchard 框架目前实现了下面的loaders:

"Referenced Module" Loader

这个loader可以在/bin目录中看到,程序集名称与在module.txt中指定的模块名称一致,如果程序集存在,将被装载并返回的它类型,这个loader当某人想要部署一个Orchard网站时非常有用,所有模块都是预编译的并存储在ASP.NET网站程序的/bin目录中.

"Core Module" Loader

如果module.txt指出模块来自于/Core目录,CoreExtensionLoader从"Orchard.Core"程序集的 "Orchard.Core.<moduleMame>" namespace返回types,"Orchard.Core"是一个特殊的程序集,包含了系统的核心模块,即提供了Orchard框架的基本功能。

 

"Precompiled Module" Loader

如果module.txt指出模块来自于/Modules目录,PrecompiledExtensionLoader在"~/Modules/<ModuleName>/bin"目录中查找一个名叫"<ModuleName>"的程序集,如果文件存在,它就会被复制到"~/App_Data/Dependencies"目录中,这是一个特殊的目录,用于ASP.NET从传统的"~/bin"之外查找额外的程序集.

"Dynamic Module" Loader

如果module.txt指出模块来自于"~/Modules"目录,"Dynamic Module" loader在"~/Modules/<ModuleName>"查找一个名叫".csproj"的文件,如果这个文件存在,该loader会为".csproj"使用Orchard build manager编译这个文件为程序集并返回程序中的types.

注意:这个loader是唯一一个系统执行中经常被称为 "dynamic compilation"的loader。

Loader Disambiguation

由于有许多loader能装载一个给定的模块,Orchard不得不有一个方式解析歧义,即找到正确的loader,每个loader有它们能装载模块的最后修改时间的能力,对于一个给定的模块,如果有多个候选loaders,Orchard

将会按 最近修改的日期返回的loader。

例如:一个给定的模块能用 包含.csproj文件和编译成程序集放进它的bin目录 两种完整的源码形式发布,第一次模块被装载,Orchard将为bin目录中的程序集选择loader,由于它很可能是在源码最后更改后被编译,不管怎样,如果源码有任何改变,"Dynamic Module" loader都将返回最近修改文件的日期(源文件或csproj)

,Orchard将为给定的模块选择那个loader。

注意:"Core Module" loader从来不是有歧义的,因为仅有一种方式装载这些模块,歧义公能在"~/Modules"目录中的模块发生。

Example

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

 

References Resolution

解释Orchard如何通过查看csproj 文件的 "References" 节也查看每个模块的bin目录中的额外二进制程序集 识别出references 。

Change of Configuration Detection

像上面解释的,模块在程序启动时装载,不过,每次程序启动,改变都会发生,可能安装了一个新模块,模块的源码可能是手动更新的,一个模块可能从网站移除了,等等,要检测这些改变,Orchard要求系统中的每个模块loader  "monitor" 潜在的变化,并当发生变化时发出通知。

当检测到变化,当前模块配置被丢弃,如果程序再重新启动了,模块会重新验证、装载和激活。在某些情况,这个改变会请求ASP.NET 应用程序域重启(如一个新版本模块程序集需要装载),Orchard检测这些状况并让ASP.NET 应用程序域重启。

Rendering Web Forms Views

TODO:解释当读取.ascx和aspx文件时,Orchard使用一个自定义的虚拟路径提供插入自定义的 "Assembly Src=xx" and "Assembly Name=xxx"指令。

 

Rendering Razor Views

TODO:解释Orchard使用一个Razor自定义的API为Views添加模块依赖。

 

The "~/App_Data/Dependencies/Dependencies.xml" File

这个文件包含了模块的列表、它们的loader和它们的 模块的”最后已知良好“的配置的参考,即Orchard最后成功装载程序模块的时间,检查这个文件的内容对于调试是很有用的,即如果一个最新版本的模块好像没有被加载。

posted @ 2012-03-26 11:20  commanderss  阅读(655)  评论(1编辑  收藏  举报