.NET下的动态代码编译探索
发布时间:2006-02-28 12:21:39 来源:VCKBASE 网友评论 0 条 不能确定动态代码编译在什么地方是有意义的?一个普通情况就应该可以帮助阐明这个问题。假如你不得不从一个数据库中取出数据并将它放入另一个数据库。你应该只需使用一个SQL语句从源数据库中选取数据并插入目标数据库中,这只是小菜一碟,对不对?如果你正在拷贝生产数据以生成测试数据并需要改变数据以确保目标数据在以后开发中使用是安全的又将如何?你可能会构建一个数据传输系统(DTS)或某个其它传输机制,但是如果你这样做超过足够多的数据,这就会变成你每次为拷贝数据建立数据-擦除(data-scrubbing)机制而消耗时间。你可以写一个应用程序来加工并生成测试数据,但是每次你在一个不同的应用程序上用它时你都将不得不改动(应用程序)并创建新的算法。
走进动态代码编译。胜于不停地写一些一次性的代码,你可以创建一个有特定内部运作机制的应用程序来传送数据并在传送时运用代码段来改变数据。该代码段将代理每个你需要在数据上要做的动作。它们将被作为原始文本被储存在一个数据库中或某个它们可以很容易被修改的其它位置。代码段将被编译并在执行时同时应用到数据。这将允许你获得一个完全是不同的代码段的数据库,使得你可以很容易地恢复、修改并应用它而不用每次都要改变你的应用程序的根本。
这是个相当复杂的情况,但是它应该帮助你理解一些可能性。现在,让我们看看如何实现它。
CodeCompileUnit(代码编译单元)
为了动态编译一个类,从System.CodeDom命名空间的一个CodeCompileUnit开始。CodeCompileUnit包含一个程序图形。为了构建代码,你要创建一些支撑对象并将它们添加到CodeCompileUnit实例中去。这些对象:代表应该已经在你的代码中的,就像你准备在设计时要创建它的普通对象。
. CodeNamespace—代表指定的命名空间
. CodeTypeDeclaration—代表类型声明
. CodeMemberMethod—代表一个方法
一个HelloWorld例子
你可以使用下面的示例代码来生成包含一个接收单个参数并返回一个值的SayHello方法的代码。scriptBody方法的参数值成为SayHello方法的实体(body)。你将你的代码包含在接收影响结果的参数的一个static(静态)类中以创建CodeCompileUnit。
| public static CodeCompileUnit CreateExecutionClass(string typeNamespace, string typeName, string scriptBody) { // 创建CodeCompileUnit以包含代码 CodeCompileUnit ccu = new CodeCompileUnit(); // 分配需要的命名空间 CodeNamespace cns = new CodeNamespace(typeNamespace); cns.Imports.Add(new CodeNamespaceImport("System")); ccu.Namespaces.Add(cns); // 创建新的类声明 CodeTypeDeclaration parentClass = new CodeTypeDeclaration(typeName); cns.Types.Add(parentClass); // 创建获得一个参数并返回一个字符串的SayHello方法 CodeMemberMethod method = new CodeMemberMethod(); method.Name = "SayHello"; method.Attributes = MemberAttributes.Public; CodeParameterDeclarationExpression arg = new CodeParameterDeclarationExpression(typeof(string), "inputMessage"); method.Parameters.Add(arg); method.ReturnType = new CodeTypeReference(typeof(string)); // 添加方法实体需要的代码 CodeSnippetStatement methodBody =new CodeSnippetStatement(scriptBody); method.Statements.Add(methodBody); parentClass.Members.Add(method); return ccu; } CodeProvider(代码提供者) |
现在你已经创建了一个CodeCompileUnit包含你的代码段,使用它来生成被编译到你的动态程序集中去的全部源代码。下面的静态方法首先从前面的例子中调用方法并且同时使用CSharpCodeProvider生成全部代码:
| public static string GenerateCode(string typeNamespace, string typeName, string scriptBody) { // 调用我们前面的方法创建CodeCompileUnit CodeCompileUnit ccu = CreateExecutionClass(typeNamespace, typeName, scriptBody); CSharpCodeProvider provider = new CSharpCodeProvider(); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BlankLinesBetweenMembers = false; options.IndentString = "/t"; StringWriter sw = new StringWriter(); try { provider.GenerateCodeFromCompileUnit(ccu, sw, options); sw.Flush(); } finally { sw.Close(); } return sw.GetStringBuilder().ToString(); } |
作为一个例子,用输入值:"CodeGuru.DynamicCode","ScriptType",和"return inputMessage;"调用GenerateCode方法得出以下输出:
| //--------------------------------------------------------------- // <auto-generated> // 该代码是由工具生成的。 // 运行时版本:2.0.50630.0 // 更改这个文件可能导致不正确的(程序)动作并且如果代码被再次生成时将会丢掉这些更改。 // </auto-generated> //--------------------------------------------------------------- namespace CodeGuru.DynamicCode { using System; public class ScriptType { public virtual string SayHello(string inputMessage) { return inputMessage; } } } |
- 推荐阅讯
- VS2005和ASP.NET2.0中使用强类型数据
- 10天学会ASP.net之第五天
- ASP.NET 2.0编程小技巧两则
- ASP.NET2.0服务器控件之创建复杂属性
- .NET正则表达式使用高级技巧之工作特点
- 剖析ASP.NET2.0站点导航功能之建立导航
- 迁移你的Web页面到ASP.NET AJAX 1.0
- 用VB.NET为智能设备编写半自动初始化类
- ASP.NET2.0中数据源控件之异步数据访问
- 用正则表达式过滤脚本的研究(ASP.net)
- 阅读排行
- 1.用ASP.NET 2.0设计网络在线投票系统
- 2.在ASP.Net 2.0中实现多语言界面的方法
- 3.轻松加密ASP.NET 2.0 Web程序配置信息
- 4.在ASP.NET中使用AJAX的简单方法
- 5..NET 2.0中的企业库异常处理块简述
- 6.面向.NET开发人员的Ajax 技术平台策略
- 7.揭开ASP.NET中Cookie编程的奥秘
- 8.ASP.NET2.0服务器控件之创建自定义控件
- 9.ASP.NET2.0中Gridview中数据操作技巧
- 10.ASP.NET 2.0发送电子邮件全面剖析之二
- 专题教程
- Windows Server-Windows Server文档-Windows Server新闻-Windows Ser PostgreSQL-PostgreSQL文档-PostgreSQL新闻-PostgreSQL专家
- WebLogic-WebLogic文档-WebLogic新闻-WebLogic专家 FreeBSD-FreeBSD文档-FreeBSD新闻-FreeBSD专家
- Linux-内核 GUI KDE Gnome DNS FTP 安全 安装-Linux专区 Windows-AD IIS ServerCore 虚拟化 安全 HPC-Windows专区
- 大话G游 专题:手机病毒揭密
- ARP攻击防范与解决方案 路由故障处理手册
