C#动态执行字符串(动态创建代码)
在编写C#程序的时候,有时我们需要动态生成一些代码并执行。然而C#不像JavaScript有一个Eval函数,可以动态的执行代码。所有这些功能都要我们自己去完成。如下是实例。
动态创建代码:
- using System;
- using System.Data;
- using System.Configuration;
- using System.Text;
- using System.CodeDom.Compiler;
- using Microsoft.CSharp;
- using System.Reflection;
- namespace EvalGuy
- {
- /// <summary>
- /// 本类用来将字符串转为可执行文本并执行
- /// 从别处复制,勿随意更改!
- /// </summary>
- public class Evaluator
- {
- #region 构造函数
- /// <summary>
- /// 可执行串的构造函数
- /// </summary>
- /// <param name="items">
- /// 可执行字符串数组
- /// </param>
- public Evaluator(EvaluatorItem[] items)
- {
- ConstructEvaluator(items); //调用解析字符串构造函数进行解析
- }
- /// <summary>
- /// 可执行串的构造函数
- /// </summary>
- /// <param name="returnType">返回值类型</param>
- /// <param name="expression">执行表达式</param>
- /// <param name="name">执行字符串名称</param>
- public Evaluator(Type returnType, string expression, string name)
- {
- //创建可执行字符串数组
- EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
- ConstructEvaluator(items); //调用解析字符串构造函数进行解析
- }
- /// <summary>
- /// 可执行串的构造函数
- /// </summary>
- /// <param name="item">可执行字符串项</param>
- public Evaluator(EvaluatorItem item)
- {
- EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组
- ConstructEvaluator(items); //调用解析字符串构造函数进行解析
- }
- /// <summary>
- /// 解析字符串构造函数
- /// </summary>
- /// <param name="items">待解析字符串数组</param>
- private void ConstructEvaluator(EvaluatorItem[] items)
- {
- //创建C#编译器实例
- ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler());
- //编译器的传入参数
- CompilerParameters cp = new CompilerParameters();
- cp.ReferencedAssemblies.Add("system.dll"); //添加程序集 system.dll 的引用
- cp.ReferencedAssemblies.Add("system.data.dll"); //添加程序集 system.data.dll 的引用
- cp.ReferencedAssemblies.Add("system.xml.dll"); //添加程序集 system.xml.dll 的引用
- cp.GenerateExecutable = false; //不生成可执行文件
- cp.GenerateInMemory = true; //在内存中运行
- StringBuilder code = new StringBuilder(); //创建代码串
- /*
- * 添加常见且必须的引用字符串
- */
- code.Append("using System; \n");
- code.Append("using System.Data; \n");
- code.Append("using System.Data.SqlClient; \n");
- code.Append("using System.Data.OleDb; \n");
- code.Append("using System.Xml; \n");
- code.Append("namespace EvalGuy { \n"); //生成代码的命名空间为EvalGuy,和本代码一样
- code.Append(" public class _Evaluator { \n"); //产生 _Evaluator 类,所有可执行代码均在此类中运行
- foreach (EvaluatorItem item in items) //遍历每一个可执行字符串项
- {
- code.AppendFormat(" public {0} {1}() ", //添加定义公共函数代码
- item.ReturnType.Name, //函数返回值为可执行字符串项中定义的返回值类型
- item.Name); //函数名称为可执行字符串项中定义的执行字符串名称
- code.Append("{ "); //添加函数开始括号
- code.AppendFormat("return ({0});", item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值
- code.Append("}\n"); //添加函数结束括号
- }
- code.Append("} }"); //添加类结束和命名空间结束括号
- //得到编译器实例的返回结果
- CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
- if (cr.Errors.HasErrors) //如果有错误
- {
- StringBuilder error = new StringBuilder(); //创建错误信息字符串
- error.Append("编译有错误的表达式: "); //添加错误文本
- foreach (CompilerError err in cr.Errors) //遍历每一个出现的编译错误
- {
- error.AppendFormat("{0}\n", err.ErrorText); //添加进错误文本,每个错误后换行
- }
- throw new Exception("编译错误: " + error.ToString());//抛出异常
- }
- Assembly a = cr.CompiledAssembly; //获取编译器实例的程序集
- _Compiled = a.CreateInstance("EvalGuy._Evaluator"); //通过程序集查找并声明 EvalGuy._Evaluator 的实例
- }
- #endregion
- #region 公有成员
- /// <summary>
- /// 执行字符串并返回整型值
- /// </summary>
- /// <param name="name">执行字符串名称</param>
- /// <returns>执行结果</returns>
- public int EvaluateInt(string name)
- {
- return (int)Evaluate(name);
- }
- /// <summary>
- /// 执行字符串并返回字符串型值
- /// </summary>
- /// <param name="name">执行字符串名称</param>
- /// <returns>执行结果</returns>
- public string EvaluateString(string name)
- {
- return (string)Evaluate(name);
- }
- /// <summary>
- /// 执行字符串并返回布尔型值
- /// </summary>
- /// <param name="name">执行字符串名称</param>
- /// <returns>执行结果</returns>
- public bool EvaluateBool(string name)
- {
- return (bool)Evaluate(name);
- }
- /// <summary>
- /// 执行字符串并返 object 型值
- /// </summary>
- /// <param name="name">执行字符串名称</param>
- /// <returns>执行结果</returns>
- public object Evaluate(string name)
- {
- MethodInfo mi = _Compiled.GetType().GetMethod(name);//获取 _Compiled 所属类型中名称为 name 的方法的引用
- return mi.Invoke(_Compiled, null); //执行 mi 所引用的方法
- }
- #endregion
- #region 静态成员
- /// <summary>
- /// 执行表达式并返回整型值
- /// </summary>
- /// <param name="code">要执行的表达式</param>
- /// <returns>运算结果</returns>
- static public int EvaluateToInteger(string code)
- {
- Evaluator eval = new Evaluator(typeof(int), code, staticMethodName);//生成 Evaluator 类的对像
- return (int)eval.Evaluate(staticMethodName); //执行并返回整型数据
- }
- /// <summary>
- /// 执行表达式并返回字符串型值
- /// </summary>
- /// <param name="code">要执行的表达式</param>
- /// <returns>运算结果</returns>
- static public string EvaluateToString(string code)
- {
- Evaluator eval = new Evaluator(typeof(string), code, staticMethodName);//生成 Evaluator 类的对像
- return (string)eval.Evaluate(staticMethodName); //执行并返回字符串型数据
- }
- /// <summary>
- /// 执行表达式并返回布尔型值
- /// </summary>
- /// <param name="code">要执行的表达式</param>
- /// <returns>运算结果</returns>
- static public bool EvaluateToBool(string code)
- {
- Evaluator eval = new Evaluator(typeof(bool), code, staticMethodName);//生成 Evaluator 类的对像
- return (bool)eval.Evaluate(staticMethodName); //执行并返回布尔型数据
- }
- /// <summary>
- /// 执行表达式并返回 object 型值
- /// </summary>
- /// <param name="code">要执行的表达式</param>
- /// <returns>运算结果</returns>
- static public object EvaluateToObject(string code)
- {
- Evaluator eval = new Evaluator(typeof(object), code, staticMethodName);//生成 Evaluator 类的对像
- return eval.Evaluate(staticMethodName); //执行并返回 object 型数据
- }
- #endregion
- #region 私有成员
- /// <summary>
- /// 静态方法的执行字符串名称
- /// </summary>
- private const string staticMethodName = "__foo";
- /// <summary>
- /// 用于动态引用生成的类,执行其内部包含的可执行字符串
- /// </summary>
- object _Compiled = null;
- #endregion
- }
- /// <summary>
- /// 可执行字符串项(即一条可执行字符串)
- /// </summary>
- public class EvaluatorItem
- {
- /// <summary>
- /// 返回值类型
- /// </summary>
- public Type ReturnType;
- /// <summary>
- /// 执行表达式
- /// </summary>
- public string Expression;
- /// <summary>
- /// 执行字符串名称
- /// </summary>
- public string Name;
- /// <summary>
- /// 可执行字符串项构造函数
- /// </summary>
- /// <param name="returnType">返回值类型</param>
- /// <param name="expression">执行表达式</param>
- /// <param name="name">执行字符串名称</param>
- public EvaluatorItem(Type returnType, string expression, string name)
- {
- ReturnType = returnType;
- Expression = expression;
- Name = name;
- }
- }
- }
调用方法:注意引用EvalGuy命名空间:
- Console.WriteLine("Test0: {0}", Evaluator.EvaluateToInteger("(30 + 4) * 2"));
- Console.WriteLine("Test1: {0}", Evaluator.EvaluateToString("\"Hello \" + \"There\""));
- Console.WriteLine("Test2: {0}", Evaluator.EvaluateToBool("30 == 40"));
- Console.WriteLine("Test3: {0}", Evaluator.EvaluateToObject("new DataSet()"));
- EvaluatorItem[] items = {
- new EvaluatorItem(typeof(int), "(30 + 4) * 2", "GetNumber"),
- new EvaluatorItem(typeof(string), "\"Hello \" + \"There\"",
- "GetString"),
- new EvaluatorItem(typeof(bool), "30 == 40", "GetBool"),
- new EvaluatorItem(typeof(object), "new DataSet()", "GetDataSet")
- };
- Evaluator eval = new Evaluator(items);
- Console.WriteLine("TestStatic0: {0}", eval.EvaluateInt("GetNumber"));
- Console.WriteLine("TestStatic1: {0}", eval.EvaluateString("GetString"));
- Console.WriteLine("TestStatic2: {0}", eval.EvaluateBool("GetBool"));
- Console.WriteLine("TestStatic3: {0}", eval.Evaluate("GetDataSet"));
转自:http://hi.baidu.com/yxw740/item/e4d256f2208590d342c36acc
C#动态执行字符串(动态创建代码)的更多相关文章
- 如何执行字符串的PHP代码
如何执行字符串的PHP代码 最近因项目需要,引出一个议题:如何执行字符串的php代码(php和html混写). 注:传统情况下,php代码存储在文件中,直接运行文件即可.以下讨论的情况是,如果php代 ...
- 第6.3节 Python动态执行之动态编译的compile函数
Python支持动态代码主要三个函数,分别是compile.eval和exec.本节介绍compile函数的语法和相关使用.compile函数用来编译一段字符串的源码,将其编译为字节码或者AST(抽像 ...
- 执行字符串或注释代码段的方法(eval、exec、execfile)
eval:计算字符串中的表达式exec:执行字符串中的语句execfile:用来执行一个文件 需注意的是,exec是一个语句,而eval()和execfile()则是内建built-in函数. 1 2 ...
- (转+整理)C#中动态执行代码
通过微软提供的CSharpCodeProvider,CompilerParameters,CompilerResults等类,可以在运行时,动态执行自己写的代码文件.原理就是把你的代码文件动态编译成e ...
- 动态执行C#代码
using System; using System.CodeDom.Compiler;using System.Collections.Generic;using System.Linq;using ...
- 执行C#动态代码
执行C#动态代码 using System; using System.Data; using System.Configuration; using System.Text; using Syste ...
- Spring Boot 创建定时任务(配合数据库动态执行)
序言:创建定时任务非常简单,主要有两种创建方式:一.基于注解(@Scheduled) 二.基于接口(SchedulingConfigurer). 前者相信大家都很熟悉,但是实际使用中我们往往想从数据库 ...
- mysql 字符串分割 和 动态执行拼接sql
本人以前主要用的是MSSQL,最近项目在使用MYSQL,自己是一个 典型的小白.今天就记录一下 一个mysql存储过程,里面需要分割字符串和 动态执行sql语句. 关于字符串 分割我开始使用 LOCA ...
- 动态执行文本vba代码
动态执行文本vba代码 Public Sub StringExecute(s As String) Dim vbComp As Object Set vbComp = ThisWorkbook.VBP ...
随机推荐
- 观察者模式及Java实现例子
http://www.cnblogs.com/mengdd/archive/2013/02/07/2908929.html 观察者模式 观察者模式 Observer 观察者模式定义了一种一对多的依赖关 ...
- visual.studio.15.preview5 编译器
前段时间微软更新了新版开发工具visual studio 15 preview5,安装后连文件结构目录都变了,想提取编译器还找不到. 不是原来的VC\BIN目录,已迁移到IDE\MSVC\14.10. ...
- [工具开发] keepalived使用nagios监控脚本
最近在做开发和办公环境的高可用,采用的是keepalived:keepalived基于Linux内核支持的LVS,既能实现高可用,又能实现负载均衡,非常实用. keepalived监控服务状态时可以用 ...
- SQL Server 2008 数据库通过镜像同步备份(数据库热备)
数据库镜像运行模式: 异步数据库镜像模式(异步,高性能模式) 同步数据库镜像模式(同步,高安全模式) 参考资料: http://technet.microsoft.com/zh-cn/library/ ...
- Notice: Trying to get property of non-object problem(PHP)解决办法 中间件只能跳转不能返任何数据
这里实际是调用了一个zend的数据库访问的方法,使用了fetchAll方法,但由于数据库中没有该记录,所以返回的对象是null,所以我就判断对象是否为null: 复制代码代码如下: if($obj== ...
- Java为什么会引入及如何使用Unsafe
综述 sun.misc.Unsafe至少从2004年Java1.4开始就存在于Java中了.在Java9中,为了提高JVM的可维护性,Unsafe和许多其他的东西一起都被作为内部使用类隐藏起来了.但是 ...
- [CF #288-C] Anya and Ghosts (贪心)
题目链接:http://codeforces.com/contest/508/problem/C 题目大意:给你三个数,m,t,r,代表晚上有m个幽灵,我有无限支蜡烛,每支蜡烛能够亮t秒,房间需要r支 ...
- Website Speed Optimization Guide for Google PageSpeed Rules
原链接地址:http://www.artzstudio.com/2016/07/website-speed-optimization-guide-for-google-pagespeed-rules/ ...
- AngularJs 简单实现全选,多选操作
很多时候我们在处理CURD(增删改查)的时候需要实现批量操作数据,这时候就必须使用多选操作. Angular 中实现如下(当然还有很多种比笔者写的更好的方法,这里只是简单的实现.) demo 演示地址 ...
- ZeroClipboard实现复制
今天利用ZeroClipboard实现了批量复制ip到剪贴版的公里,第一种方式总是有错,需要点击两次才能成功复制,第二种方法成功.在这里记录下,方法一: $('#copy_ips').zclip({ ...