zoukankan      html  css  js  c++  java
  • .Net拾忆:CodeDom动态源代码生成器和编译器

    代码文档模型CodeDom命名空间下主要有两个,很明显第一个代码逻辑分析,第二个负责代码的编译

    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.CodeDom;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Practice.CodeDom.Compiler
    {
        class Program
        {
            static void Main(string[] args)
            {
                Program pro = new Program();
                CodeNamespace nspace = pro.CreateCodeDomHelloDemo();
                Console.WriteLine(pro.GengerCode(nspace));
                string filename = "HelloWorld.exe";
                CompilerResults result = pro.Execute(nspace, filename);
                if (result.Errors.HasErrors)//是否存在错误;
                {
                    for (int i = 0; i < result.Output.Count; i++)
    
                        Console.WriteLine(result.Output[i]);
    
                    for (int i = 0; i < result.Errors.Count; i++)
    
                        Console.WriteLine(i.ToString() + ": " + result.Errors[i].ToString());
                }
                else
                {
                    System.Diagnostics.Process.Start(filename);//这里比较懒,不想动手去自己打开,呵呵;
                }
                Console.Read();
            }
    
            public CodeNamespace CreateCodeDomHelloDemo()
            {
                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();
    
                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());
    
                CodeTypeDeclaration helloword = new CodeTypeDeclaration("HelloWord");//类型Class声明
                helloword.Attributes = MemberAttributes.Public;
                helloword.Members.AddRange(new CodeTypeMember[] { method, main });//添加方法到clss
    
                CodeNamespace nspace = new CodeNamespace("HelloDemo1");//命名空间声明
                nspace.Imports.Add(new CodeNamespaceImport("System"));//引入程序命名空间:using System;
                nspace.Types.Add(helloword);//
                return nspace;
            }
    
            public string GengerCode(CodeNamespace nspace)
            {
                StringBuilder sb = new StringBuilder();
                System.IO.StringWriter sw = new System.IO.StringWriter(sb);
                CodeGeneratorOptions geneOptions = new CodeGeneratorOptions();//代码生成选项
    
                geneOptions.BlankLinesBetweenMembers = false;
    
                geneOptions.BracingStyle = "C";
    
                geneOptions.ElseOnClosing = true;
    
                geneOptions.IndentString = "    ";
                CodeDomProvider.GetCompilerInfo("c#").CreateProvider().GenerateCodeFromNamespace(nspace, sw, geneOptions);//代码生成
                sw.Close();
                return sb.ToString();
    
            }
    
            public CompilerResults Execute(CodeNamespace nspace, string filename)
            {
                CodeCompileUnit unit = new CodeCompileUnit();//code编译单元
                unit.Namespaces.Add(nspace);
                CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
                CompilerParameters options = new CompilerParameters();//
    
                options.GenerateInMemory = false;//是否在内存中生成;
                options.IncludeDebugInformation = true;// 包含调试信息;
                options.ReferencedAssemblies.Add("System.dll");
                options.OutputAssembly = filename;
                if (System.IO.Path.GetExtension(filename).ToLower() == ".exe")
                {
                    options.GenerateExecutable = true;//true为可执行exe,false:dll
                }
                else
                {
                    options.GenerateExecutable = false;//true为可执行exe,false:dll
                }
                return provider.CompileAssemblyFromDom(options, unit);//编译程序集
            }
        }
    }
    HelloWorld

    示例二

    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

  • 相关阅读:
    php 字符串查找
    php缓存与加速分析与汇总
    oracle 时间问题
    mysql数据迁移
    浅谈千万级PV/IP规模高性能高并发网站架构
    对memcache分布式的一点理解
    美国程序员将工作廉价外包给中国公司遭解雇
    16个Linux服务器监控命令
    在yii中使用memcache
    Windows电脑快捷健大全
  • 原文地址:https://www.cnblogs.com/xmai/p/7086656.html
Copyright © 2011-2022 走看看