C#发现之旅:于动态编译的VB.NET脚本引擎(上)
2010-09-30 21:08:18 来源:WEB开发网VB.NET脚本原理
VB.NET脚本就是采用VB.NET语法的脚本。VS.NET集成开发环境提供的宏也是采用VB.NET语法。微软.NET框架提供了一个脚本引擎,那就是在程序集microsoft.visualbasic.vsa.dll中的类型Microsfot.VisualBasic.Vsa.VsaEngine,该类型在微软.NET框架1.1和2.0中都有,使用起来不算容易,而且在微软.NET框架2.0中VsaEngine类型标记为“已过时”。在此笔者不使用VsaEngine类型来实现VB.NET脚本,而是使用动态编译技术来实现脚本引擎。
使用动态编译技术实现VB.NET脚本引擎的原理是,程序将用户的脚本代码字符串进行一些预处理,然后调用Microsoft.VisualBasic.VBCodeProvider类型的CompileAssemblyFromSource函数进行动态编译,生成一个临时的程序集对象,使用反射技术获得程序集中的脚本代码生成的方法,主程序将按照名称来调用这些脚本代码生成的方法。若用户修改了脚本代码,则这个过程重复一次。
VB.NET脚本引擎设计
这里笔者将用倒推法来设计VB.NET脚本引擎,也就是从预期的最终使用结果来反过来设计脚本引擎。
主程序将按照名称来调用脚本方法,很显然VB.NET代码编译生成的是一个.NET程序集类库,为了方便起见,笔者将所有的VB.NET脚本方法集中到一个VB.NET脚本类型。笔者将脚本方法定义为静态方法,主要有两个好处,首先脚本引擎不必生成对象实例,其次能避免由于没有生成对象实例而导致的空引用错误,这样能减少脚本引擎的工作量。
在VB.NET语法中,可以使用代码块“public shared sub SubName()”来定义一个静态过程,但笔者不能要求用户在编写VB.NET脚本代码时使用“public shared sub SubName()”的VB.NET语法,而只能使用“sub SubName()”这样比较简单的语法。同样用户在脚本中定义全局变量时不能使用“private shared VarName as TypeName”的语法,而是简单的使用“dim VarName as TypeName”的语法。这时笔者可以使用VB.NET语法的模块的概念。在VB.NET语法中,将代码块“Module ModuleName ……. End Module”中的所有的代码编译为静态的。比如把“sub SubName”编译成“public shared sub SubName()”,把“dim VarName as TypeName”编译为“public shared VarName as TypeName”。这样借助VB.NET模块的概念就能解决了这个问题。
更多精彩
赞助商链接