[转载]Oxite2插件机制分析

[转载]Oxite2插件机制分析 – xuefly – 博客园.

由于Oxite1ASP.NET MVC1还未发布的时候就早早地发布了,2009215日发布的Oxite1口碑不好,但是即将发布的经过重新开发的Oxite2已经不再羸弱了,有非常多的值得观察与学习的地方。本文讨论的内容是基于Oxite2的,你可以在这里下载到最新的Oxite源码:http://oxite.codeplex.com/SourceControl/ListDownloadableCommits.aspx

欢迎加入Oxite小组一起学习:博客园Oxite小组

Oxite2的插件机制分析

一般,插件机制是基于接口实现的。但是Oxite2的插件机制是基于“约定”的。既然接口的本意是必须履行的“契约”,即,签订者必须履行的约定(签订者指非抽象类,对契约补充条款还是契约,不是契约的签订者),那么,这样说的话Oxite2的插件机制也可以算是基于“接口”的啦。“契约”是必须履行的,“约定”是非强制履行的。

小组希望我写一些关于Oxite2的插件机制的文字。我以前没有接触过插件机制,因此答应介绍这个话题,因为我可以就着Oxite2的源码趁机学习一下哈。我们小组是Oxite2开源项目学习小组,这篇文章的内容主要是通过对Oxite2代码的学习得来的,所以文章谈论的内容局限于Oxite2的插件机制,并不是ASP.NET插件机制的总结性文章。我尽最大努力保证文章内容的正确性,对于不正确的地方一定要指出来。

您需要深入理解以下内容作为阅读本文的前提:

1, 程序集

2, 反射

3, 特性(Attribute

4, 最好了解:linq, 委托,lambda

另外您还需要一份Oxite2源码

l 使用System.Web.Compilation.BuildManager动态编译代码文件为程序集

首先,Oxite2的插件机制是使用BuildManager.GetCompiledAssembly(string virtualPath)方法“将文件编译为‘给定了虚拟路径的程序集’”的。双引号内的文字摘自MSDN,单引号内的内容实在难以理解(查英文MSDN原文为:Compiles a file into an assembly given its virtual path.)希望有理解单引号内的内容的朋友回复。我先不管这个,我们先通过实验熟悉一下该方法,在HomeController中书写如下代码:

public void Compile()

{

Assembly assembly = BuildManager.GetCompiledAssembly(Request.ApplicationPath + “Plugins/HelloWorld.cs”);

Response.Write(“assembly.FullName:<br />” + assembly.FullName);

Response.Write(“<br />”);

Response.Write(“assembly.Location:<br />” + assembly.Location);

}

è 请求http://localhost:2801/Home/Compile

è 输出结果:

assembly.FullName:
App_Web_helloworld.cs.3b296ce9.iicat0p2,Version=0.0.0.0,Culture=neutral, PublicKeyToken=null
assembly.Location:
C:”Windows”Microsoft.NET”Framework”v2.0.50727″Temporary ASP.NET Files”root”836b6d34″9df6dbcc”App_Web_helloworld.cs.3b296ce9.iicat0p2.dll

好了,对BuildManager的介绍就到这里,更详细的请查看MSDN。下面贴一张图:

说明:作为插件,TwitterPlugins.cs文件的编译选项被设置为Content而不是Compile,对它的编译由我们通过使用BuildManager编码进行而不是使用VS管理编译。

上图Plugins文件夹下的cs代码是和“.aspx”等文件中声明式的代码一样通过BuildManager编译的。区别是“.aspx”等文件是在第一次请求到他们时即时编译并缓存到“Temporary ASP.NET Files”系统目录的,而对插件代码文件的编译是由我们控制的,仅此区别。Oxite2的插件机制对Plugins文件夹递归并把每一个“.cs”或者“.vb”后缀的文件编译成相应的程序集,每一个代码文件对应一个程序集(每一个”.aspx”文件也是对应一个程序集,并且App_Code特殊对待,App_Code中的每一个文件夹编译成一个程序集,对于非App_Code文件夹中的代码WebSite项目和WebApp项目编译方式不同)。

在我们了解了如何通过使用BuildManager把代码文件编译为程序集之后,后面的内容就可以直接展开了。

Oxite2插件机制

首先是PluginAssemblyContainerPluginContainer。这两个具有继承关系的类分别是对“插件程序集”和该程序集中的“插件”封装的容器类。


其中图上所说的“类级别特性”全都继承自DefinitionAttribute而“属性级别特性”全都继承自PropertyDefinitionAttribute

由于这两种类型的特性定义的实在太多了,并且Oxite2还有还有第二种方案——使用特定方式命名的属性和匿名类型的属性值取代特性。所以这里就不贴类图上来了。介绍一个我在学习中总结的方法,大家一看便知:比如现在我们要研究Oxite项目的ViewModels文件夹下的类:


我们首先建一个.cd文件,按照一定规则命名该类图文件,然后将ViewModels文件夹拖到该打开的类图文件上,VS就会自动给我们绘制好类图了,如下:


说明:VS绘出的ViewModels文件夹下的类的类结构图

另外VS绘制类图的功能不是仅仅支持源代码,对于dll文件照样是可以的。不过对于dll文件我们需要做的是拖放命名空间到打开的类图上,而不是拖放文件夹或者dll文件。现在你可以进去VS的对象浏览器对任何一个.NET Framework中的命名空间按照上面的说明操作一下试试了。如果有条件的话,把自己不是很熟悉的.NET命名空间下的类打印出来贴在墙上是一个不错的主意。

按照上面介绍的方法对Oxite项目中Plugins文件夹下的代码进行研究很多东西都是一目了然的啦,由于类文件太多,类图太大,大部分类仅仅是离散的用来封装数据的类,贴类图没有价值。所以这里只贴上来类文件列表并对列表上的类做一点说明:


Plugins文件夹下的代码就是Oxite2的插件机制的基础构架,而Oxite项目的Modules文件夹下的Plugins文件夹中的代码正是基于该基础架构的Plugins系统模块的实现。


我们看上图中的Plugins系统模块,从类文件的组织结构看和《浅谈Oxite2的数据访问和数据验证》中所分析的结构完全一样。可以参考上一篇熟悉Plugins的数据访问和业务逻辑层。到这里应该差不多了,其实从通过使用BuildManager编译出程序集开始,下面就是很明显的方案了:加载程序集并维护一个插件程序集列表 => 通过反射反射出所有插件程序集中的插件并维护一个插件列表 => 通过反射调用插件中的约定命名的方法注册插件信息 => 通过反射“特性”或者特定命名的属性的匿名类型的属性值并使用上一步注册的模板显示数据。

下图:Oxite2中已有的Xbox Live Gamercard插件的效果



说明:可以在后台直接编辑cs源代码,重新编译代码文件,重新加载插件程序集,重新加载插件,应用程序不必重启。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏