Orchard 源码探索(Module,Theme,Core扩展加载概述)
参考: http://www.orchardch.com/Blog/20120830071458
1. host.Initialize();
1
2
3
4
5
6
7
8
|
private static IOrchardHost HostInitialization(HttpApplication application) {
var host = OrchardStarter.CreateHost(MvcSingletons);
host.Initialize();
// initialize shells to speed up the first dynamic query
host.BeginRequest();
host.EndRequest();
return host;
} |
Orchard作为一个可扩展的CMS系统,需要在初始化或运行时加载一些模块(Modules)或主题(Themes),这些模块或主题统称扩展(Extensions)。
1
2
3
4
5
|
host.Initialize(); //Called once on startup to configure app domain, and load/apply existing shell configuration SetupExtensions(); //在初始化过程中会对扩展进行设置
MonitorExtensions(); //当添加新的扩展、删除扩展、修改扩展源码后,需要通知扩展加载器(Extension Loader)重新加载或完成一些清理工作,所以需要进行监视:
CreateAndActivateShells(); //Orchard是一个多租户(Tenant)系统,也就是我们通常所是说的子站点,它允许一个Orchard应用程序中包含多个不同域名的子站点。每个子站点对应一个Shell,需要创建并激活.
|
1.SetupExtensions
加载所有扩展,并判断应用程序域是否需要重新启动。 涉及到了CacheManager类:Todo
IParallelCacheContext类:并行缓存类
Orchard包括三种扩展:Core,Theme,Module.
123456folder.AvailableExtensions()
HarvestExtensions(...)
//looking for extensions
private
List<ExtensionDescriptor> AvailableExtensionsInFolder(
string
path,
string
extensionType,
string
manifestName,
bool
manifestIsOptional)
var
descriptor = GetExtensionDescriptor(path, extensionId, extensionType, manifestPath, manifestIsOptional);
_webSiteFolder.ReadFile(manifestPath);
追根溯源到了file.open。 在此过程中有很多类和功能被忽略掉了,只注意到了主要的脉络,那就是加载扩展的流程。如果被半路的过多细节所羁绊的话,会发现时间是个无底洞。稍后会对在此过程中的一些典型的问题进行梳理,争取做到法网烣烣。
2.MonitorExtensions
当扩展变更或新增时,通过把_current值设为null来促使扩展加载协调类通知orchard,需要重新加载新的或已经变更的扩展。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public void MonitorExtensionsWork(Action<IVolatileToken> monitor) {
Logger.Information( "Start monitoring extension files..." );
// Monitor add/remove of any module/theme
Logger.Debug( "Monitoring virtual path \"{0}\"" , "~/Modules" );
monitor(_virtualPathMonitor.WhenPathChanges( "~/Modules" ));
Logger.Debug( "Monitoring virtual path \"{0}\"" , "~/Themes" );
monitor(_virtualPathMonitor.WhenPathChanges( "~/Themes" ));
// Give loaders a chance to monitor any additional changes
var extensions = _extensionManager.AvailableExtensions().Where(d => DefaultExtensionTypes.IsModule(d.ExtensionType) || DefaultExtensionTypes.IsTheme(d.ExtensionType)).ToList();
foreach ( var extension in extensions) {
foreach ( var loader in _loaders) {
loader.Monitor(extension, monitor);
}
}
Logger.Information( "Done monitoring extension files..." );
}
|
3.CreateAndActivateShells
加载所有的子站点,并激活它们的shell.
1
2
3
4
5
6
7
8
9
10
11
|
IEnumerable<ShellSettings> IShellSettingsManager.LoadSettings(); private const string _settingsFileName = "Settings.txt" ;
private IEnumerable<ShellSettings> LoadSettingsInternal() {
var filePaths = _appDataFolder
.ListDirectories( "Sites" )
.SelectMany(path => _appDataFolder.ListFiles(path))
.Where(path => String.Equals(Path.GetFileName(path), _settingsFileName, StringComparison.OrdinalIgnoreCase));
foreach ( var filePath in filePaths) {
yield return ShellSettingsSerializer.ParseSettings(_appDataFolder.ReadFile(filePath));
}
}
|
显然分为两步,一步是通过app_data文件夹下的Setting.txt加载所有子站点的配置也就是反序列化;第二步ActivateShell(context);
==========================
Orchard.Environment.DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler
Orchard.Environment.IOrchardHost(DefaultOrchardHost)对象用来初始化程序域及Shell(每个子站点对应一个shell)的配置,加载或重加载已存在的模块或扩展。
世界是你们的,也是我们的,但归根结底是他们的。