jstovb.net的简单介绍(11)


最新net频点播系统
php基于php学生成绩管理系统软件的开发
最新neterp系统(毕业设计
原创vc基于bs方式的即时通讯软件
基于lotus的故障报修系统
vf超市配送运输管理系统
vb.net试卷生成系统
原创文件压缩与解压缩实践
php教师档案管理系统
原创jsp《信息论与编码》在线考试系统
android网络数据包捕获工具
jsp药品销售数据管理系统
asp在线学习系统
j2ee考勤管理系统j2ee
asp网络商城
c局域网即时聊天程序
c#健身中心会员管理系统
vf客房管理信息系统
java基于采集
netxx职业中学图书管理系统的设计
基于caché的实验室资源管理系统的设计
最新基于net教学辅助系统设计与实现
vb.net学生管理系统
c内存映射文件在进程共享中的应用研究
vf中国象棋游戏
vbsmart系统-题库及试卷管理模块的设计与开发
win平台下的pe文件病毒的研究及实现
net基于手机短信平台聊天程序
jsp网上图书销售系统
原创web的入侵防御系统
vc干部档案管理系统
最新web的入侵防御系统
vf基于misty算法的加密软件的实现
vb.net数据结构辅助教学
php个人日志系统
asp.net论坛程序设计(万字功能强大)
asp网页设计辅导系统
最新net动态口令认证的网上选课系统
net基于.net电子相册的开发
j2ee学生信息管理系统万字
pb网上交易系统pb
vf超市进销存管理系统vf报稿
asp留言板
c#模拟atm机系统软件的设计与开发c#
asp交友录
pb车辆
如何在.NET中实现脚本引擎NET本身提供了强大的脚本引擎 , 可以直接使用.NETCLR的任何编程语言作为脚本语言,如VB.NET、C#、JScript,J#等等 。使用脚本引擎,我们可以动态生成任意表达式、或动态导入任意脚本文件,并在任意时候执行 。经实践发现,我们可以使用至少两种不同的方式在.NET中使用脚本引擎:VsaEngine和CodeDom 。其实,CodeDom不能算是真正的脚本引擎 , 它实际上是编译器 。但是我们完全可以利用CodeDom来模拟脚本引擎 。使用Emit方法也能达到动态生成可执行代码的目的,而且Emit生成的代码不需要编译,因此速度更快 。但是Emit插入的实际上是汇编代码,不能算是脚本语言 。本文介绍如何以CodeDom方式来动态生成可执行代码 。如何在.NET中实现脚本引擎(CodeDom篇)沐枫网志1.构造一个编译器设置编译参数编译参数需要在CompilerParameters设置:CompilerOptions用于设置编译器命令行参数IncludeDebugInformation用于指示是否在内存在生成AssemblyGenerateInMemory用于指示是否在内存在生成AssemblyGenerateExecutable用于指示生成的Assembly类型是exe还是dllOutputAssembly用于指示生成的程序文件名(仅在GenerateInMemory为false的情况)ReferencedAssemblies用于添加引用Assembly例如:theParameters.ReferencedAssemblies.Add("System.dll");创建指定语言的编译器编译需要由指定语言的CodeDomProvider生成 。这里列举一些.NET的CodeDomProvider:vb.netMicrosoft.VisualBasic.VBCodeProviderC#Microsoft.CSharp.CSharpCodeProviderjscriptMicrosoft.JScript.JScriptCodeProviderJ#Microsoft.VJSharp.VJSharpCodeProvider以C#为例,要创建C#编译器 , 代码如下://.NET1.1/1.0ICodeCompilercompiler=newMicrosoft.CSharp.CSharpCodeProvider().CreateCompiler();//.NET2.0ICodeCompilercompiler=(ICodeCompiler)newMicrosoft.CSharp.CSharpCodeProvider();下面是完整的创建编译器的例子://////创建相应脚本语言的编译器///privatevoidcreateCompiler(stringstrLanguage,booldebugMode,stringstrAssemblyFileName){this.theParameters=newCompilerParameters();this.theParameters.OutputAssembly=System.IO.Path.Combine(System.IO.Path.GetTempPath(),strAssemblyFileName+".dll");this.theParameters.GenerateExecutable=false;this.theParameters.GenerateInMemory=true;if(debugMode){this.theParameters.IncludeDebugInformation=true;this.theParameters.CompilerOptions+="/define:TRACE=1/define:DEBUG=1";}else{this.theParameters.IncludeDebugInformation=false;this.theParameters.CompilerOptions+="/define:TRACE=1";}AddReference("System.dll");AddReference("System.Data.dll");AddReference("System.Xml.dll");strLanguage=strLanguage.ToLower();CodeDomProvidertheProvider;if("visualbasic"==strLanguage||"vb"==strLanguage){theProvider=newMicrosoft.VisualBasic.VBCodeProvider();if(debugMode)theParameters.CompilerOptions+="/debug:full/optimize-/optionexplicit+/optionstrict+/optioncompare:text/imports:Microsoft.VisualBasic,System,System.Collections,System.Diagnostics";elsetheParameters.CompilerOptions+="/optimize/optionexplicit+/optionstrict+/optioncompare:text/imports:Microsoft.VisualBasic,System,System.Collections,System.Diagnostics";AddReference("Microsoft.VisualBasic.dll");}elseif("jscript"==strLanguage||"js"==strLanguage){theProvider=newMicrosoft.JScript.JScriptCodeProvider();AddReference("Microsoft.JScript.dll");}elseif("csharp"==strLanguage||"cs"==strLanguage||"c#"==strLanguage){theProvider=newMicrosoft.CSharp.CSharpCodeProvider();if(!debugMode)theParameters.CompilerOptions+="/optimize";}//elseif("jsharp"==strLanguage||"vj"==strLanguage||"j#"==strLanguage)//{//theProvider=newMicrosoft.VJSharp.VJSharpCodeProvider();//if(!debugMode)//theParameters.CompilerOptions+="/optimize";//}elsethrownewSystem.Exception("指定的脚本语言不被支持 。");this.theCompiler=theProvider.CreateCompiler();}//////添加引用对象 。//////引用的文件名publicvoidAddReference(string__strAssemblyName){theParameters.ReferencedAssemblies.Add(__strAssemblyName);}注:在.NETFramework2.0中,由于CreateCompiler方法被标记作废 。为避免产生编译警告 , 可直接返回CodeDomProvider作为编译器:this.theCompiler=(ICodeCompiler)theProvider;2.编译源代码编译源代码相当简单 , 只需一条语句就搞定了:CompilerResultscompilerResults=compiler.CompileAssemblyFromSource(this.theParameters,this.SourceText);执行后,可以从compilerResults取得以下内容:NativeCompilerReturnValue编译结果,用于检查是否成功Errors编译时产生的错误和警告信息CompiledAssembly如果编译成功,则返回编译生成的Assembly示例函数://////编译脚本 。编译前将清空以前的编译信息 。///CompilerInfo将包含编译时产生的错误信息 。//////成功时返回True 。不成功为False 。publicboolCompile(){this.theCompilerInfo="";this.isCompiled=false;this.theCompiledAssembly=null;this.theCompilerResults=this.theCompiler.CompileAssemblyFromSource(this.theParameters,this.SourceText);if(this.theCompilerResults.NativeCompilerReturnValue=https://www.04ip.com/post/=0){this.isCompiled=true;this.theCompiledAssembly=this.theCompilerResults.CompiledAssembly;}System.Text.StringBuildercompilerInfo=newSystem.Text.StringBuilder();foreach(CompilerErrorerrinthis.theCompilerResults.Errors){compilerInfo.Append(err.ToString());compilerInfo.Append("/r/n");}theCompilerInfo=compilerInfo.ToString();returnisCompiled;}3.执行代码使用Reflection机制就可以很方便的执行Assembly中的代码 。我们假设编译时使用的脚本代码this.SourceText内容如下:namespacetest{publicclassscript{staticpublicvoidMain(){MessageBox.Show("Hello");}}}则相应的执行代码为:scriptEngine.Invoke("test.script","Main",null);Invoke函数内容://////执行指定的脚本函数(Method) 。///如果指定的类或模块名,以及函数(Method)、或参数不正确,将会产生VsaException/VshException例外 。//////类或模块名///要执行的函数(Method)名字///参数(数组)///返回执行的结果publicobjectInvoke(string__strModule,string__strMethod,object[]__Arguments){if(!this.IsCompiled||this.theCompiledAssembly==null)thrownewSystem.Exception("脚本还没有成功编译");Type__ModuleType=this.theCompiledAssembly.GetType(__strModule);if(null==__ModuleType)thrownewSystem.Exception(string.Format("指定的类或模块({0})未定义 。",__strModule));MethodInfo__MethodInfo=__ModuleType.GetMethod(__strMethod);if(null==__MethodInfo)thrownewSystem.Exception(string.Format("指定的方法({0}::{1})未定义 。",__strModule,__strMethod));try{return__MethodInfo.Invoke(null,__Arguments);}catch(TargetParameterCountException){thrownewSystem.Exception(string.Format("指定的方法({0}:{1})参数错误 。",__strModule,__strMethod));}catch(System.Exceptione){System.Diagnostics.Trace.WriteLine(string.Format("执行({0}:{1})错误:{2}",__strModule,__strMethod,e.ToString()));returnnull;}}总结:CodeDom可以很方便的随时编译源代码,并动态执行 。虽然作为脚本引擎,它没有VsaEngine正规和方便,但作为一般应用,也够用了 。并且结合Reflection机制 , 它的功能比VsaEngine更强大:它可以编译任何提供CompilerProvider的CLR语言(目前.NET自带的语言中都有) 。当然 , 它也有一些缺点:它生成的Assembly不能动态卸载 。这在一般情况下不成问题,因为一个源代码只需编译一次,并载入执行,并不需要动态卸载 。假如你需要做脚本编辑器时,就要考虑这个问题,因为有可能一个脚本会因为修修改改而不停的重新编译 , 从而造成不停的产生新的Assembly , 最后将导致内存被大量占用 。要解决这个问题,需要将编译器加载到独立的AppDomain中 , 通过卸载AppDomain达到卸载所需的Assembly的目的 。

推荐阅读