在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
1、简介 能够动态执行 C# 代码是一件很酷的功能,比如,我们可以在控制台中输入一行 C# 代码,然后程序自动编译并执行这一行代码,将结果显示给我们。这差不多就是一个最简单的 C# 代码解释器了。 动态执行 C# 代码又是一件很有用的功能,比如,我们可以将某些代码写在某个文件之中,由程序集在执行时进行加载,改变这些代码不用中止程序,当程序再次加载这些代码时,就自动执行的是新代码了。 下面,我将在写一个简单C# 代码解释器,然后将在 C# 代码解释器之中加入动态代码与解释器环境间的动态交互机制,来演示一个很好很强大的应用。 2、简单的 C# 代码解释器 关于如何动态执行 C# 代码在 Jailu.Net 的《如何用C#动态编译、执行代码》一文中讲述的很清晰。采用该文所述方式写一个 C# 代码解释器:
using System;
using System.Collections.Generic; using System.Reflection; using System.Globalization; using Microsoft.CSharp; using System.CodeDom; using System.CodeDom.Compiler; using System.Text; using System.IO; using System.Xml; namespace Test 编译执行后就得到一个傻傻的 C# 代码解析器,也可以当一个简单的计算器用: 3、解释器与所解释的代码之间进行变量交互 如果将所解释的代码中的某些变量储存下来,供给以后的代码用,这一解释器的功能又会强大很多。假设这类变量名称以$打头,如: $myblogname = “http://xiaotie.cnblogs.com” 将在解释器环境中定义(如果该变量未存在)或赋值于(如果该变量已存在)一个名为 myblogname 的字符串变量,指向字符串“http://xiaotie.cnblogs.com”。而,System.Console.WriteLine($myblogname)则取出并打印出字符串该变量所引用的。 简单说来,也就是让所解释的代码中能够初始化并引用解释器中的变量。 如何实现呢?这是本文的重点。 首先,在 Context 类中定义一个SortedDictionary储存变量,并提供索引访问:
}
BuildFullCmd方法改变为:
private String BuildFullCmd(String inputCmdString)
} 这样,在动态生成的对象中,便可以引用Context对象。 对于inputCmdString 中未定义的外部变量,在第一次遇见时将$argname替换为一个随机生成的内部变量,在代码的最后,将这个内部变量储存在 Context 中。 虽然通过 (Context[argname].GetType())(Context[argname]) 便可引用外部变量 $argname,但是这样引用赋值时,编译器会报错。解决这个问题需要一个新的类:
public class ObjectHelper<T>
} 将inputCmdString中的外部变量$argname统一替换为(new ObjectHelper <m_context[“argname”].GetType()> (m_context, “argname”)).Obj" 即可实现在动态代码中对已定义外部变量的引用。 上述对inputCmdString的预处理代码为:
Regex re;
// 处理未初始化的环境变量 re = new Regex(@"^(\$)(\w)+"); if (inputCmdString != null) } 这里做了个简化,即定义外部变量的格式必须为 $argname = value,其中 $argname 必须在行首。 这样,对于:$myblogname = "http://xiaotie.cnblogs.com". 因为 myblogname 变量不存在,被解析为: 定义后,当再出现 $myblogname,则被解析为 (new ObjectHelper<System.String>(m_context,"myblogname")).Obj; 看看实际执行情况: 4、一个很好很强大的应用—---打入.Net 程序内部,看看其执行情况。 采用上面的方法改进了 OrcShell(OrcShell详情见我前面的随笔: 实现简单的CSharpShell -- OrcShell )。新版 OrcShell 程序于此下载(需要.Net 3.5)。基本上是一个可用的 小型 .Net Framework Shell 了,可以动态的查看、创建、执行 .Net 的类型了。不过,自动提示与完成功能还没有做,使用起来还是较不方便的。 help 指令可以查看常用指令列表: lsc 列出当前命名空间中的类型和下属命名空间。格式: lsc [name] |
请发表评论