change
![](/icons/70943set.gif)
:42353
download :http://oxite.codeplex.com/SourceControl/ListDownloadableCommits.aspx
和
![](/icons/70943yi.gif)
般
![](/icons/70943de.gif)
web
![](/icons/70943chengxu.gif)
![](/icons/70943yi.gif)
样
![](/icons/70943dou.gif)
Oxite在第
![](/icons/70943yi.gif)
次被访问时将进行
![](/icons/70943chushi.gif)
化操作
![](/icons/70943dou.gif)
即Oxite.OxiteApplication
![](/icons/70943de.gif)
Application_Start思路方法
![](/icons/70943dou2.gif)
这些操作笼统来说包括两部分
![](/icons/70943dou.gif)
![](/icons/70943yi.gif)
是设置依赖注入容器并将的存入应用
![](/icons/70943chengxu.gif)
状态中(HttpApplicationState)
![](/icons/70943dou.gif)
2是通过依赖注入容器中
![](/icons/70943de.gif)
某些配置加载模块(Oxite分析的Module)
这两部分
![](/icons/70943de.gif)
分析入口分别为Application_Start思路方法中
![](/icons/70943de.gif)
Application["container"] =
![](/icons/70943set.gif)
upContainer
![](/icons/70943kh.gif)
;和load
![](/icons/70943kh.gif)
;
![](/icons/70943yi.gif)
、设置依赖注入容器
注意力转移至
![](/icons/70943set.gif)
upContainer思路方法
![](/icons/70943dou2.gif)
该思路方法直接或间接将大批
![](/icons/70943de.gif)
对象和类型注册入依赖注入容器
首先
![](/icons/70943dou.gif)
将几个基础对象注册为单例
1: parentContainer
2: .RegisterInstance((OxiteConfigurationSection)ConfigurationManager.GetSection("oxite"))
3: .RegisterInstance(
AppSettingsHelper(ConfigurationManager.AppSettings))
4: .RegisterInstance(RouteTable.Routes)
5: .RegisterInstance(
.Web.Mvc.ModelBinders.Binders)
6: .RegisterInstance(ViewEngines.Engines)
7: .RegisterInstance(HostingEnvironment.VirtualPathProvider);
OxiteConfigurationSectio类
![](/icons/70943dou.gif)
自定义配置节点
![](/icons/70943dou2.gif)
其下目前有 3个属性:connectionStrings,dataProviders,moduls(可能会增加
![](/icons/70943yi.gif)
个
![](/icons/70943set.gif)
tings属性)
![](/icons/70943dou2.gif)
可以查看OxiteSite项目下
![](/icons/70943de.gif)
oxite.confing文件直观
![](/icons/70943de.gif)
了解其结构
![](/icons/70943dou2.gif)
该配置基本上是针对Module
![](/icons/70943de.gif)
(Oxite分析的Module)
Oxite几乎将所有东西都放置在
![](/icons/70943yi.gif)
个个模块中
![](/icons/70943dou.gif)
包括最核心
![](/icons/70943de.gif)
部分
![](/icons/70943dou2.gif)
比如设置自定义CollectionerFactiory、自定义ControllerActionInvoker、自定义ViewEngines等在Oxite.Moduls.Core模块中进行
![](/icons/70943dou2.gif)
而moduls节点就定义了Oxite系统包括哪些Module;
dataProviders定义了各个需要数据访问
![](/icons/70943de.gif)
Module
![](/icons/70943de.gif)
数据访问方式
![](/icons/70943de.gif)
分类(category属性)
![](/icons/70943dou.gif)
而在Module
![](/icons/70943de.gif)
具体定义中可以这个分类注入区别
![](/icons/70943de.gif)
Repository以达到各个模块可以单独使用区别
![](/icons/70943de.gif)
数据访问方式设置区别
![](/icons/70943de.gif)
数据库
connectionStrings节点结构和站点配置web.config中
![](/icons/70943de.gif)
系统connectionStrings节点完全相同
![](/icons/70943dou.gif)
这里的所以又进行
![](/icons/70943yi.gif)
次定义
![](/icons/70943dou.gif)
是为了提供给dataProviders使用(dataProviders有个defaultConnectionString属性)
![](/icons/70943dou2.gif)
当dataProviders下
![](/icons/70943de.gif)
元素未定义connectionString时
![](/icons/70943dou.gif)
可以使用dataProviders节点
![](/icons/70943de.gif)
defaultConnectionString属性对应
![](/icons/70943de.gif)
connectionStrings节点
![](/icons/70943de.gif)
元素
![](/icons/70943de.gif)
connectionString属性(真拗口)
AppSettingsHelper 类对ConfigurationManager.AppSettings 进行包装, 提供几个读取思路方法GetInt32、GetString等
![](/icons/70943dou.gif)
用于读取web.config文件中
![](/icons/70943de.gif)
appSettings节点下
![](/icons/70943de.gif)
值
![](/icons/70943dou2.gif)
其实完全可以将这几个读取思路方法放入NameValueCollectionExtensions类(Oxite已定义该类)
![](/icons/70943dou2.gif)
appSettings节点下
![](/icons/70943dou.gif)
可以定义名称为Oxite.InstanceName
![](/icons/70943de.gif)
值来指定Oxite例子
![](/icons/70943dou.gif)
该值指导
![](/icons/70943chengxu.gif)
在数据库读取Oxite_Site表中
![](/icons/70943de.gif)
相应配置
![](/icons/70943dou2.gif)
还可以定义名称为IsEmail、IsUrl等
![](/icons/70943dou.gif)
值为正则表达式
![](/icons/70943de.gif)
元素
![](/icons/70943dou2.gif)
如果appSettings节点中没有定义这些元素
![](/icons/70943dou.gif)
将会使用
![](/icons/70943chengxu.gif)
硬编码中
![](/icons/70943de.gif)
设置
RouteTable.Routes
![](/icons/70943dou.gif)
RouteCollection对象
![](/icons/70943dou2.gif)
![](/icons/70943System.gif)
.Web.Routing中对其定义
![](/icons/70943dou.gif)
稍微熟悉
![](/icons/70943yi.gif)
点ASP.NET MVC应该清楚这是做什么
![](/icons/70943de.gif)
另外ModelBinders.Binders、ViewEngines.Engines 可以参看有关ASP.NET MVC方面
![](/icons/70943de.gif)
资料
HostingEnvironment.VirtualPathProvider
![](/icons/70943dou.gif)
HostingEnvironment 类
![](/icons/70943de.gif)
静态属性
![](/icons/70943dou.gif)
其值是VirtualPathProvider类
![](/icons/70943de.gif)
对象
![](/icons/70943dou2.gif)
个人猜测可能会用在自定义ViewEngine中
![](/icons/70943dou.gif)
不过目前Oxite版本中好像还没地方用
然后
![](/icons/70943dou.gif)
将web.config中
![](/icons/70943de.gif)
connectionStrings和自定义节点”oxite”下
![](/icons/70943de.gif)
connectionStrings注册为单件
1: foreach (ConnectionStringSettings connectionString in ConfigurationManager.ConnectionStrings)
2: parentContainer.RegisterInstance(connectionString.Name, connectionString.ConnectionString);
3:
4: foreach (ConnectionStringSettings connectionString in parentContainer.Resolve<OxiteConfigurationSection>
.ConnectionStrings)
5: parentContainer.RegisterInstance(connectionString.Name, connectionString.ConnectionString);
将数据库连接
![](/icons/70943zifu.gif)
串注册为单件
![](/icons/70943dou.gif)
在构造数据库访问对象(或ORM,Linq to Sql、Entity Framework等)将会使用
接着,两行咋看不太起眼
![](/icons/70943de.gif)
代码
![](/icons/70943dou.gif)
实际上是进入Oxite核心
![](/icons/70943de.gif)
入口:
1: parentContainer
2: .RegisterInstance<IBootStrapperTask>("LoadModules",
LoadModules(parentContainer));
创建LoadModules对象
![](/icons/70943dou.gif)
并注册为单例
![](/icons/70943dou2.gif)
LoadModules实现了IBootStrapperTask接口
1: public
erface IBootStrapperTask
2: {
3: void Execute(IDictionary<
, object> state);
4: void Cleanup(IDictionary<
, object> state);
5: }
在OxiteApplication
![](/icons/70943de.gif)
Application_Start
![](/icons/70943diaoyong.gif)
私有思路方法load,load
![](/icons/70943diaoyong.gif)
静态思路方法 Load
![](/icons/70943dou2.gif)
Load思路方法中
![](/icons/70943dou.gif)
将从依赖注入容器中提取(ResolveAll)所有实现了IBootStrapperTask接口
![](/icons/70943de.gif)
类
![](/icons/70943de.gif)
对象
![](/icons/70943dou.gif)
并
![](/icons/70943diaoyong.gif)
Execute思路方法(详情查看静态思路方法Load);在Application_End思路方法中
![](/icons/70943dou.gif)
类似
![](/icons/70943de.gif)
将间接执行实现了IBootStrapperTask接口
![](/icons/70943de.gif)
类
![](/icons/70943de.gif)
对象
![](/icons/70943de.gif)
Cleanup思路方法(详情查看私有思路方法unload)
![](/icons/70943dou2.gif)
当然
![](/icons/70943dou.gif)
目前Oxite版本中只有
![](/icons/70943yi.gif)
个LoadModules对象
LoadModules类
![](/icons/70943de.gif)
主要代码:
1: public void Execute(IDictionary<
, object> state)
2: {
3: OxiteConfigurationSection config = container.Resolve<OxiteConfigurationSection>
;
4: IModulesLoaded modulesLoaded = this.container.Resolve<IModulesLoaded>
;
5: RouteCollection routes = this.container.Resolve<RouteCollection>
;
6: IFilterRegistry filterRegistry = this.container.Resolve<FilterRegistry>
;
7: ModelBinderDictionary modelBinders = this.container.Resolve<ModelBinderDictionary>
;
8: IBackgroundServiceRegistry backgroundServicesRegistry = this.container.Resolve<IBackgroundServiceRegistry>
;
9:
10: filterRegistry.Clear
;
11:
12: modelBinders.Clear
;
13:
14: //todo: (nheskew) get plugin routes registered on load in the right order instead of just clearing the routes before module init
15: routes.Clear
;
16:
17: foreach (OxiteModuleConfigurationElement module in config.Modules)
18: {
19: IOxiteModule moduleInstance = modulesLoaded.Load(config, module);
20:
21:
(moduleInstance != null)
22: {
23: moduleInstance.RegisterWithContainer
;
24: moduleInstance.Initialize
;
25: moduleInstance.RegisterFilters(filterRegistry);
26: moduleInstance.RegisterModelBinders(modelBinders);
27:
28: this.container.RegisterInstance(modulesLoaded);
29:
30: //TODO: (erikpo) Move this
o its own BootStrapper and spin up the appropriate executor
es and start them
31: IOxiteBackgroundService backgroundServices = moduleInstance as IOxiteBackgroundService;
32:
33:
(backgroundServices != null)
34: backgroundServices.RegisterBackgroundServices(backgroundServicesRegistry);
35: }
36: }
37:
38: routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
39:
40: routes.LoadFromModules(modulesLoaded);
41:
42: routes.LoadCatchAllFromModules(modulesLoaded);
43:
44: container.RegisterInstance(filterRegistry);
45:
46: container.RegisterInstance(backgroundServicesRegistry);
47: }
48:
49: public void Cleanup(IDictionary<
, object> state)
50: {
51: container.Resolve<IModulesLoaded>
.UnloadModules
;
52:
53: //TODO: (erikpo) Loop through all background services running in the background and stop them
54: }
在这里我们暂时不去关心IBackgroundServiceRegistry、IFilterRegistry和FilterRegistry
![](/icons/70943de.gif)
定义
![](/icons/70943dou.gif)
不过通过接口名称可以看出是和后台服务和ActionFilter相关
![](/icons/70943de.gif)
下面简单说说Oxite如何实现Module(Oxite分析的Module)
![](/icons/70943de.gif)
插拔功能
![](/icons/70943de.gif)
Oxite中
![](/icons/70943de.gif)
Module都实现了IOxiteModule接口
![](/icons/70943dou2.gif)
当做好
![](/icons/70943yi.gif)
个Module后(源码文件.cs或.vb等)
![](/icons/70943dou.gif)
直接复制到OxiteSet
![](/icons/70943de.gif)
App_Code目录下
![](/icons/70943dou.gif)
或者编译成dll复制到bin目录下并在依赖注入容器中进行注入
![](/icons/70943dou.gif)
然后在oxite配置节点中进行配置即可
![](/icons/70943dou2.gif)
轻松实现Module
![](/icons/70943de.gif)
插拔功能
IModulesLoaded接口
![](/icons/70943dou.gif)
从字面上看就是”已经加载
![](/icons/70943de.gif)
Module”,在Oxite中有
![](/icons/70943yi.gif)
个实现:ModulesLoaded类
![](/icons/70943dou.gif)
在依赖注入容器中已经进行了注册:parentContainer.RegisterType<IModulesLoaded, ModulesLoaded>
![](/icons/70943dou2.gif)
该类
![](/icons/70943de.gif)
Load思路方法正是实现上述Module插拔功能
Load思路方法中将找到
![](/icons/70943de.gif)
Module例子化
![](/icons/70943dou.gif)
并将对象私有变量List<IOxiteModule> modules中
![](/icons/70943dou.gif)
分别提供泛型和非泛型
![](/icons/70943de.gif)
GetModules思路方法供外部读取
![](/icons/70943dou2.gif)
当然
![](/icons/70943dou.gif)
这种插拔功能如果完全可以自己另外实现
![](/icons/70943yi.gif)
个:parentContainer.RegisterType<IModulesLoaded, MyModulesLoaded>
![](/icons/70943kh.gif)
然后再看看IOxiteModule接口
IOxiteModule接口定义了7个思路方法:
1: public
erface IOxiteModule
2: {
3: void Initialize
;
4: void Unload
;
5: void RegisterRoutes(RouteCollection routes);
6: void RegisterCatchAllRoutes(RouteCollection routes);
7: void RegisterFilters(IFilterRegistry filterRegistry);
8: void RegisterModelBinders(ModelBinderDictionary modelBinders);
9: void RegisterWithContainer
;
10: }
11:
在LoadModules类
![](/icons/70943de.gif)
Execute思路方法中
![](/icons/70943de.gif)
![](/icons/70943dou.gif)
查看foreach循环:
foreach (XoohooModuleConfigurationElement module in container.Resolve<XoohooConfigurationSection>
![](/icons/70943kh.gif)
.Modules)
对oxite配置节点获取moduls节点
![](/icons/70943de.gif)
所有元素进行遍历
IOxiteModule moduleInstance = modulesLoaded.Load(config, module);
ModulesLoaded类例子modulesLoaded
![](/icons/70943de.gif)
Load思路方法将Module进行例子化
![](/icons/70943dou.gif)
返回IOxiteModule对象
![](/icons/70943dou2.gif)
如果正常返回IOxiteModule对象,就
![](/icons/70943diaoyong.gif)
如下 4个思路方法: RegisterWithContainer
Initialize
RegisterFilters
RegisterModelBinders
接着:
this.container.RegisterInstance(modulesLoaded);
作用是将”已经加载
![](/icons/70943de.gif)
Module”注册为单例
这句写在循环里
![](/icons/70943dou.gif)
为什么不写在循环外面?
接下来
![](/icons/70943de.gif)
几句是有关后台服务
![](/icons/70943de.gif)
![](/icons/70943dou.gif)
略去
跳出循环后:
1: routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
2:
3: routes.LoadFromModules(modulesLoaded);
4:
5: routes.LoadCatchAllFromModules(modulesLoaded);
6:
第
![](/icons/70943yi.gif)
句代码比较熟悉
![](/icons/70943dou.gif)
排除axd文件
![](/icons/70943de.gif)
路由
第 2、 3行代码
![](/icons/70943dou.gif)
![](/icons/70943diaoyong.gif)
RouteCollection类型
![](/icons/70943de.gif)
扩展思路方法LoadFromModules和LoadCatchAllFromModules
![](/icons/70943dou2.gif)
这两个思路方法实际上分别执行所有”已经加载
![](/icons/70943de.gif)
Module”
![](/icons/70943de.gif)
IModulesLoaded.LoadFromModules思路方法和IModulesLoaded.LoadCatchAllFromModules
这里有
![](/icons/70943yi.gif)
个疑问
![](/icons/70943dou.gif)
这两行代码为什么没有像
![](/icons/70943diaoyong.gif)
ModulesLoaded类
![](/icons/70943de.gif)
RegisterWithContainer,Initialize,RegisterFilters,RegisterModelBinders这 4个思路方法那样
![](/icons/70943diaoyong.gif)
:
1: routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
2:
3: foreach (OxiteModuleConfigurationElement module in config.Modules)
4: {
5: IOxiteModule moduleInstance = modulesLoaded.Load(config, module);
6:
7:
(moduleInstance != null)
8: {
9: moduleInstance.RegisterWithContainer
;
10: moduleInstance.Initialize
;
11: moduleInstance.RegisterFilters(filterRegistry);
12: moduleInstance.RegisterModelBinders(modelBinders);
13: moduleInstance.RegisterRoutes(routes);
14: moduleInstance.RegisterCatchAllRoutes(routes);
15:
16: this.container.RegisterInstance(modulesLoaded);
17: //...
18: }
19: }
20:
![](/icons/70943set.gif)
upContainer思路方法接下来注册
![](/icons/70943de.gif)
类型
![](/icons/70943dou.gif)
除非了ModulesLoaded
![](/icons/70943dou.gif)
其他
![](/icons/70943de.gif)
目前还不能直接分析
2、静态思路方法Load
静态思路方法Load在被load思路方法
![](/icons/70943diaoyong.gif)
,load思路方法被Applaction_Start思路方法
![](/icons/70943diaoyong.gif)
![](/icons/70943dou2.gif)
也就是说
![](/icons/70943dou.gif)
Load思路方法在站点第
![](/icons/70943yi.gif)
次被访问时
![](/icons/70943dou.gif)
就会被
![](/icons/70943diaoyong.gif)
1: public
void Load(HttpContextBase context)
2: {
3: IEnumerable<IBootStrapperTask> tasks = ((IUnityContainer)context.Application["container"]).ResolveAll<IBootStrapperTask>
;
4: bool bootStrappersLoaded = (bool)context.Application["bootStrappersLoaded"];
5: IDictionary<
, object> state = (IDictionary<
, object>)context.Application["bootStrapperState"];
6:
7:
(state
null)
8: {
9: context.Application["bootStrapperState"] = state =
Dictionary<
, object>
;
10: }
11:
12: // If the tasks have been executed previously, call Cleanup on them to rollback any changes
13: // they caused.
14:
(bootStrappersLoaded)
15: {
16: foreach (IBootStrapperTask task in tasks)
17: {
18: task.Cleanup(state);
19: }
20: }
21:
22: foreach (IBootStrapperTask task in tasks)
23: {
24: task.Execute(state);
25: }
26:
27: context.Application["bootStrappersLoaded"] = true;
28: }
29:
Application["bootStrapperState"]保存
![](/icons/70943yi.gif)
个状态值
![](/icons/70943dou.gif)
指示站点时候已经
![](/icons/70943chushi.gif)
化
Application["bootStrappersLoaded"]
![](/icons/70943dou.gif)
可以查看后台服务
![](/icons/70943de.gif)
实现部分
Load思路方法首先获取实现IBootStrapperTask接口并注册入依赖注入容器
![](/icons/70943de.gif)
所有例子并保存入局部变量IEnumerable<IBootStrapperTask> tasks
![](/icons/70943dou2.gif)
通过的前
![](/icons/70943de.gif)
分析我们知道
![](/icons/70943dou.gif)
目前tasks集合中也就只有
![](/icons/70943yi.gif)
个对象:LoadModules对象
state部分暂时略去
![](/icons/70943dou.gif)
看下面
![](/icons/70943de.gif)
部分:
1:
(bootStrappersLoaded)
2: {
3: foreach (IBootStrapperTask task in tasks)
4: {
5: task.Cleanup(state);
6: }
7: }
8:
9: foreach (IBootStrapperTask task in tasks)
10: {
11: task.Execute(state);
12: }
13:
如果站点已经
![](/icons/70943chushi.gif)
化首先进行清理操作
![](/icons/70943dou.gif)
然后再重新执行
如果需要在运行时候重新加载模块,在其他地方
![](/icons/70943diaoyong.gif)
Load也是可以
![](/icons/70943de.gif)
![](/icons/70943dou.gif)
从而可以实现真正
![](/icons/70943de.gif)
Module热插拔