.Net拾忆:CodeDom动态源代码生成器和编译器
2017-06-28 08:47
260 查看
代码文档模型CodeDom命名空间下主要有两个,很明显第一个代码逻辑分析,第二个负责代码的编译
2、CodeTypeDeclaration类定义
3、CodeMemberMethod/CodeEntryPointMethod方法
4、CodeMethodInvokeExpression表达式
CodeDomProvider创建编译器
CompilerParameters编译器参数
CompilerResults编译结果
示例一
动态编译字符串示例
资料:
类库:
https://msdn.microsoft.com/zh-cn/library/system.codedom.compiler(v=vs.110).aspx
示例文档:
https://msdn.microsoft.com/zh-cn/library/650ax5cx(v=vs.110).aspx
快速参考:
https://msdn.microsoft.com/zh-cn/library/f1dfsbhc(v=vs.110).aspx
博客
http://www.cnblogs.com/whitewolf/archive/2010/06/19/1760708.html
工具:
C#>VB:
http://www.dotnetspider.com/convert/CSharp-To-Vb.aspx
using System.CodeDom; using System.CodeDom.Compiler;
一、代码逻辑
1、CodeNamespace创建命名空间CodeNamespace nspace=new CodeNamespace("Practice.MyNamespace")//创建命名空间 nspace.Imports.Add(new CodeNamespaceImport("System"));//引入程序命名空间:using System; //nspace.Types 命名空间中所含类的集合,使用add添加
2、CodeTypeDeclaration类定义
CodeTypeDeclaration helloword = new CodeTypeDeclaration("HelloWord");//类型Class声明 helloword.Attributes = MemberAttributes.Public;//public //helloword.Members.AddRange(new CodeTypeMember[] { method, main });//添加方法到clss
3、CodeMemberMethod/CodeEntryPointMethod方法
CodeMemberMethod method = new CodeMemberMethod();//方法声明; method.Name = "SayHello";// 方法名 method.Attributes = MemberAttributes.Public | MemberAttributes.Final;//属性 method.ReturnType = new CodeTypeReference(typeof(string));//返回类型 method.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression("Hello from code!"))); //方法体,只有一句返回语句return "Hello from code!"; CodeEntryPointMethod main = new CodeEntryPointMethod();//主方法Main main.Statements.Add(new CodeVariableDeclarationStatement("HelloWord", "hw", new CodeObjectCreateExpression("HelloWord", new CodeExpression[] { })));//变量声明:HelloWord hw = new HelloWord();
4、CodeMethodInvokeExpression表达式
CodeMethodInvokeExpression methodinvoke = new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("hw"), "SayHello", new CodeExpression[] { }); main.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"), "WriteLine", methodinvoke)); main.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"), "Read")); //两个方法调用:System.Console.WriteLine(hw.SayHello());
二、编译
System.CodeDom.Compiler常用类CodeDomProvider创建编译器
CodeDomProvider provider = CodeDomProvider.CreateProvider("VisualBasic"); CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
CompilerParameters编译器参数
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll"); //添加程序集 system.dll 的引用 cp.GenerateExecutable = false; //不生成可执行文件 cp.GenerateInMemory = true; //在内存中运行
CompilerResults编译结果
//得到编译器实例的返回结果 CompilerResults cr = provider.CompileAssemblyFromSource(cp, code.ToString())
cr.Errors //CompilerError集合、所有编译错误 cr.CompiledAssembly //Assembly、 获取编译结果的程序集
示例一
using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
namespace Practice.Common
{
/// <summary>
/// 本类用来将字符串转为可执行文本并执行
/// </summary>
public class DynamicEvaluator
{
#region 构造函数
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="items">
/// 可执行字符串数组
/// </param>
public DynamicEvaluator(EvaluatorItem[] items)
{
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="returnType">返回值类型</param>
/// <param name="expression">执行表达式</param>
/// <param name="name">执行字符串名称</param>
public DynamicEvaluator(Type returnType, string expression, string name)
{
//创建可执行字符串数组
EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="item">可执行字符串项</param>
public DynamicEvaluator(EvaluatorItem item)
{
EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 解析字符串构造函数
/// </summary>
/// <param name="items">待解析字符串数组</param>
private void ConstructEvaluator(EvaluatorItem[] items)
{
//创建C#编译器实例
CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
//过时了
//ICodeCompiler comp = provider.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; ");
code.Append("using System.Xml; ");
code.Append("using System.Collections.Generic; ");
code.Append("namespace Flow { "); //生成代码的命名空间为EvalGuy,和本代码一样
code.Append(" public class _Evaluator { "); //产生 _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("}"); //添加函数结束括号
}
code.Append("} }"); //添加类结束和命名空间结束括号
//得到编译器实例的返回结果
CompilerResults cr = provider.CompileAssemblyFromSource(cp, code.ToString());//comp
if (cr.Errors.HasErrors) //如果有错误
{
StringBuilder error = new StringBuilder(); //创建错误信息字符串
error.Append("编译有错误的表达式: "); //添加错误文本
foreach (CompilerError err in cr.Errors) //遍历每一个出现的编译错误
{
error.AppendFormat("{0}", err.ErrorText); //添加进错误文本,每个错误后换行
}
throw new Exception("编译错误: " + error.ToString());//抛出异常
}
Assembly a = cr.CompiledAssembly; //获取编译器实例的程序集
_Compiled = a.CreateInstance("Flow._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 double EvaluateDouble(string name)
{
return (double)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回长整型数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public long EvaluateLong(string name)
{
return (long)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回十进制数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public decimal EvaluateDecimal(string name)
{
return (decimal)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)
{
DynamicEvaluator eval = new DynamicEvaluator(typeof(int), code, staticMethodName);//生成 Evaluator 类的对像
return (int)eval.Evaluate(staticMethodName); //执行并返回整型数据
}
/// <summary>
/// 执行表达式并返回双精度值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
static public double EvaluateToDouble(string code)
{
DynamicEvaluator eval = new DynamicEvaluator(typeof(double), code, staticMethodName);//生成 Evaluator 类的对像
return (double)eval.Evaluate(staticMethodName);
}
/// <summary>
/// 执行表达式并返回长整型数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
static public long EvaluateToLong(string code)
{
DynamicEvaluator eval = new DynamicEvaluator(typeof(long), code, staticMethodName);//生成 Evaluator 类的对像
return (long)eval.Evaluate(staticMethodName);
}
/// <summary>
/// 执行表达式并返回十进制数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
static public decimal EvaluateToDecimal(string code)
{
DynamicEvaluator eval = new DynamicEvaluator(typeof(decimal), code, staticMethodName);//生成 Evaluator 类的对像
return (decimal)eval.Evaluate(staticMethodName);
}
/// <summary>
/// 执行表达式并返回字符串型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public string EvaluateToString(string code)
{
DynamicEvaluator eval = new DynamicEvaluator(typeof(string), code, staticMethodName);//生成 Evaluator 类的对像
return (string)eval.Evaluate(staticMethodName); //执行并返回字符串型数据
}
/// <summary>
/// 执行表达式并返回布尔型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public bool EvaluateToBool(string code)
{
DynamicEvaluator eval = new DynamicEvaluator(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)
{
DynamicEvaluator eval = new DynamicEvaluator(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;
}
}
}
动态编译字符串示例
资料:
类库:
https://msdn.microsoft.com/zh-cn/library/system.codedom.compiler(v=vs.110).aspx
示例文档:
https://msdn.microsoft.com/zh-cn/library/650ax5cx(v=vs.110).aspx
快速参考:
https://msdn.microsoft.com/zh-cn/library/f1dfsbhc(v=vs.110).aspx
博客
http://www.cnblogs.com/whitewolf/archive/2010/06/19/1760708.html
工具:
C#>VB:
http://www.dotnetspider.com/convert/CSharp-To-Vb.aspx
相关文章推荐
- 微软开放.net的部分源代码(c#编译器等)
- 深入解析.NET 许可证编译器 (Lc.exe) 的原理与源代码剖析
- 深入解析.NET 许可证编译器 (Lc.exe) 的原理与源代码剖析
- 动态生成与编译(七)----根据CodeDOM生成源代码
- 【.net 深呼吸】细说CodeDom(9):动态编译
- 解析.NET 许可证编译器 (Lc.exe) 的原理与源代码剖析
- 使用 .Net Framework 的 System.CodeDom 命名空间动态生成源代码并编译
- .Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)
- Silverlight Visifire控件 .net后台控制aspx页面控件的显示与隐藏,动态给控件赋值,选定默认值的设定
- 在.NET 3.5 平台上使用LINQ to SQL创建三层/多层Web应用系统(源代码下载和PDF文档下载)(转载)
- 精进不休 .NET 4.0 (3) - asp.net 4.0 新特性之动态数据(Dynamic Data)增强, AJAX增强; IDE之Visual Studio 2010增强
- 谷歌地图上动态标注数字文字等图标 源代码整理
- .NET 4.0 里的默认参数原来是编译器搞的鬼啊
- .net下两种json序列化速度比对(已添加源代码下载地址)
- .NET:动态代理的 “5 + 1” 模式
- 使用动态包导出函数的单元的完整源代码
- 使用反射在.NET中实现动态工厂
- .net动态加载程序集和影子复制(Dynamic Load Assembly and Shadow Copy)
- 关于.NET动态代理的介绍和应用简介
- php显示动态时间源代码