专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » oxite:Oxite分析的初始化 »正文

oxite:Oxite分析的初始化

来源: 发布时间:星期二, 2009年9月8日 浏览:0次 评论:0
  change :42353

  download :http://oxite.codeplex.com/SourceControl/ListDownloadableCommits.aspx

  和webOxite在第次被访问时将进行化操作即Oxite.OxiteApplicationApplication_Start思路方法这些操作笼统来说包括两部分是设置依赖注入容器并将的存入应用状态中(HttpApplicationState) 2是通过依赖注入容器中某些配置加载模块(Oxite分析的Module)

  这两部分分析入口分别为Application_Start思路方法中Application["container"] = upContainer;和load;

  、设置依赖注入容器

  注意力转移至upContainer思路方法该思路方法直接或间接将大批对象和类型注册入依赖注入容器

  首先将几个基础对象注册为单例

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类自定义配置节点其下目前有 3个属性:connectionStrings,dataProviders,moduls(可能会增加tings属性)可以查看OxiteSite项目下oxite.confing文件直观了解其结构该配置基本上是针对Module(Oxite分析的Module)

  Oxite几乎将所有东西都放置在个个模块中包括最核心部分比如设置自定义CollectionerFactiory、自定义ControllerActionInvoker、自定义ViewEngines等在Oxite.Moduls.Core模块中进行而moduls节点就定义了Oxite系统包括哪些Module;

  dataProviders定义了各个需要数据访问Module数据访问方式分类(category属性)而在Module具体定义中可以这个分类注入区别Repository以达到各个模块可以单独使用区别数据访问方式设置区别数据库

  connectionStrings节点结构和站点配置web.config中系统connectionStrings节点完全相同这里的所以又进行次定义是为了提供给dataProviders使用(dataProviders有个defaultConnectionString属性)当dataProviders下元素未定义connectionString时可以使用dataProviders节点defaultConnectionString属性对应connectionStrings节点元素connectionString属性(真拗口)

  AppSettingsHelper 类对ConfigurationManager.AppSettings 进行包装, 提供几个读取思路方法GetInt32、GetString等用于读取web.config文件中appSettings节点下其实完全可以将这几个读取思路方法放入NameValueCollectionExtensions类(Oxite已定义该类)appSettings节点下可以定义名称为Oxite.InstanceName值来指定Oxite例子该值指导在数据库读取Oxite_Site表中相应配置还可以定义名称为IsEmail、IsUrl等值为正则表达式元素如果appSettings节点中没有定义这些元素将会使用硬编码中设置

  RouteTable.RoutesRouteCollection对象.Web.Routing中对其定义稍微熟悉点ASP.NET MVC应该清楚这是做什么

  另外ModelBinders.Binders、ViewEngines.Engines 可以参看有关ASP.NET MVC方面资料

  HostingEnvironment.VirtualPathProviderHostingEnvironment 类静态属性其值是VirtualPathProvider类对象个人猜测可能会用在自定义ViewEngine中不过目前Oxite版本中好像还没地方用

  然后将web.config中connectionStrings和自定义节点”oxite”下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);  


  将数据库连接串注册为单件在构造数据库访问对象(或ORM,Linq to Sql、Entity Framework等)将会使用

  接着,两行咋看不太起眼代码实际上是进入Oxite核心入口:

1: parentContainer
2:   .RegisterInstance<IBootStrapperTask>("LoadModules",  LoadModules(parentContainer));  


  创建LoadModules对象并注册为单例LoadModules实现了IBootStrapperTask接口

1: public erface IBootStrapperTask
2: {
3:   void Execute(IDictionary<, object> state);
4:   void Cleanup(IDictionary<, object> state);
5: }  


  在OxiteApplicationApplication_Start私有思路方法load,load静态思路方法 LoadLoad思路方法中将从依赖注入容器中提取(ResolveAll)所有实现了IBootStrapperTask接口对象Execute思路方法(详情查看静态思路方法Load);在Application_End思路方法中类似将间接执行实现了IBootStrapperTask接口对象Cleanup思路方法(详情查看私有思路方法unload)当然目前Oxite版本中只有个LoadModules对象

  LoadModules类主要代码:

 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定义不过通过接口名称可以看出是和后台服务和ActionFilter相关

  下面简单说说Oxite如何实现Module(Oxite分析的Module)插拔功能

  Oxite中Module都实现了IOxiteModule接口当做好个Module后(源码文件.cs或.vb等)直接复制到OxiteSetApp_Code目录下或者编译成dll复制到bin目录下并在依赖注入容器中进行注入然后在oxite配置节点中进行配置即可轻松实现Module插拔功能

  IModulesLoaded接口从字面上看就是”已经加载Module”,在Oxite中有个实现:ModulesLoaded类在依赖注入容器中已经进行了注册:parentContainer.RegisterType<IModulesLoaded, ModulesLoaded>

  该类Load思路方法正是实现上述Module插拔功能

  Load思路方法中将找到Module例子化并将对象私有变量List<IOxiteModule> modules中分别提供泛型和非泛型GetModules思路方法供外部读取当然这种插拔功能如果完全可以自己另外实现个:parentContainer.RegisterType<IModulesLoaded, MyModulesLoaded>

  然后再看看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类Execute思路方法中查看foreach循环:

  foreach (XoohooModuleConfigurationElement module in container.Resolve<XoohooConfigurationSection>.Modules)

  对oxite配置节点获取moduls节点所有元素进行遍历

  IOxiteModule moduleInstance = modulesLoaded.Load(config, module);

  ModulesLoaded类例子modulesLoadedLoad思路方法将Module进行例子化返回IOxiteModule对象如果正常返回IOxiteModule对象,就如下 4个思路方法:       RegisterWithContainer

  Initialize

  RegisterFilters

  RegisterModelBinders

  接着:

  this.container.RegisterInstance(modulesLoaded);

  作用是将”已经加载Module”注册为单例

  这句写在循环里为什么不写在循环外面?

  接下来几句是有关后台服务略去

  跳出循环后:

1: routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
2:  
3: routes.LoadFromModules(modulesLoaded);
4:  
5: routes.LoadCatchAllFromModules(modulesLoaded);
6:  


  第句代码比较熟悉排除axd文件路由

  第 2、 3行代码RouteCollection类型扩展思路方法LoadFromModules和LoadCatchAllFromModules这两个思路方法实际上分别执行所有”已经加载Module”IModulesLoaded.LoadFromModules思路方法和IModulesLoaded.LoadCatchAllFromModules

  这里有个疑问这两行代码为什么没有像ModulesLoaded类RegisterWithContainer,Initialize,RegisterFilters,RegisterModelBinders这 4个思路方法那样:

 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:  


  upContainer思路方法接下来注册类型除非了ModulesLoaded其他目前还不能直接分析

   2、静态思路方法Load

  静态思路方法Load在被load思路方法,load思路方法被Applaction_Start思路方法也就是说Load思路方法在站点第次被访问时就会被

 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"]保存个状态值指示站点时候已经

  Application["bootStrappersLoaded"]可以查看后台服务实现部分

  Load思路方法首先获取实现IBootStrapperTask接口并注册入依赖注入容器所有例子并保存入局部变量IEnumerable<IBootStrapperTask> tasks通过的前分析我们知道目前tasks集合中也就只有个对象:LoadModules对象

  state部分暂时略去看下面部分:

 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:  


  如果站点已经化首先进行清理操作然后再重新执行

  如果需要在运行时候重新加载模块,在其他地方Load也是可以从而可以实现真正Module热插拔



0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: