[C#] C#动态编译,实现按钮功能动态配置 →→→→→进入此内容的聊天室

来自 , 2019-10-16, 写在 C#, 查看 139 次.
URL http://www.code666.cn/view/75429d13
  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.IO;
  5. using System.Text;
  6. using System.CodeDom.Compiler;
  7. using System.Windows.Forms;
  8. using Microsoft.CSharp;
  9. using System.Reflection;
  10.  
  11. namespace DynamicAddFunction
  12. {
  13.     /// <summary>  
  14.     /// 本类用来将字符串转为可执行文本并执行,用于动态定义按钮响应的事件。
  15.     /// </summary>  
  16.     public class Evaluator
  17.     {
  18.         private string filepath = Path.Combine(Application.StartupPath, "FunBtn.config");
  19.      
  20.         #region 构造函数
  21.         /// <summary>  
  22.         /// 可执行串的构造函数  
  23.         /// </summary>  
  24.         /// <param name="items">  
  25.         /// 可执行字符串数组  
  26.         /// </param>  
  27.         public Evaluator(EvaluatorItem[] items)
  28.         {
  29.             ConstructEvaluator(items);      //调用解析字符串构造函数进行解析  
  30.         }
  31.         /// <summary>  
  32.         /// 可执行串的构造函数  
  33.         /// </summary>  
  34.         /// <param name="returnType">返回值类型</param>  
  35.         /// <param name="expression">执行表达式</param>  
  36.         /// <param name="name">执行字符串名称</param>  
  37.         public Evaluator(Type returnType, string expression, string name)
  38.         {
  39.             //创建可执行字符串数组  
  40.             EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
  41.             ConstructEvaluator(items);      //调用解析字符串构造函数进行解析
  42.         }
  43.         /// <summary>  
  44.         /// 可执行串的构造函数  
  45.         /// </summary>  
  46.         /// <param name="item">可执行字符串项</param>  
  47.         public Evaluator(EvaluatorItem item)
  48.         {
  49.             EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组  
  50.             ConstructEvaluator(items);      //调用解析字符串构造函数进行解析  
  51.         }
  52.         /// <summary>  
  53.         /// 解析字符串构造函数  
  54.         /// </summary>  
  55.         /// <param name="items">待解析字符串数组</param>  
  56.         private void ConstructEvaluator(EvaluatorItem[] items)
  57.         {
  58.             //创建C#编译器实例  
  59.             //ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler());
  60.             CSharpCodeProvider comp = new CSharpCodeProvider();
  61.             //编译器的传入参数  
  62.             CompilerParameters cp = new CompilerParameters();
  63.  
  64.             Configer configer = Configer.Current(filepath);
  65.             string[] assemblies = configer.GetAssembly("FunBtn//assembly//dll","name");
  66.             cp.ReferencedAssemblies.AddRange(assemblies);           //添加程序集集合
  67.             //cp.ReferencedAssemblies.Add("system.dll");              //添加程序集 system.dll 的引用  
  68.             //cp.ReferencedAssemblies.Add("system.data.dll");         //添加程序集 system.data.dll 的引用  
  69.             //cp.ReferencedAssemblies.Add("system.xml.dll");          //添加程序集 system.xml.dll 的引用  
  70.             //cp.ReferencedAssemblies.Add("system.windows.forms.dll");
  71.             //cp.ReferencedAssemblies.Add("FunButton.dll");
  72.             //cp.ReferencedAssemblies.Add("DynamicAddFunction.exe");
  73.             cp.GenerateExecutable = false;                          //不生成可执行文件  
  74.             cp.GenerateInMemory = true;                             //在内存中运行  
  75.  
  76.             StringBuilder code = new StringBuilder();               //创建代码串  
  77.             /*
  78.              * 添加常见且必须的引用字符串
  79.              */
  80.             //获取引用的命名空间
  81.             string[] usings = configer.GetAssembly("FunBtn//assembly//using", "name");
  82.  
  83.             foreach (var @using in usings)
  84.             {
  85.                 code.Append(@using+"\n");//添加引用的命名空间
  86.             }
  87.             //code.Append("using System; \n");
  88.             //code.Append("using System.Data; \n");
  89.             //code.Append("using System.Data.SqlClient; \n");
  90.             //code.Append("using System.Data.OleDb; \n");
  91.             //code.Append("using System.Xml; \n");
  92.             //code.Append("using FunButton; \n");
  93.             //code.Append("using System.Windows.Forms; \n");
  94.             //code.Append("using DynamicAddFunction; \n");
  95.  
  96.             code.Append("namespace EvalGuy { \n");                  //生成代码的命名空间为EvalGuy,和本代码一样  
  97.  
  98.             code.Append(" public class _Evaluator { \n");          //产生 _Evaluator 类,所有可执行代码均在此类中运行  
  99.             foreach (EvaluatorItem item in items)               //遍历每一个可执行字符串项  
  100.             {
  101.                 code.AppendFormat("    public {0} {1}() ",          //添加定义公共函数代码  
  102.                                   item.ReturnType.Name.ToLower() ,             //函数返回值为可执行字符串项中定义的返回值类型  
  103.                                   item.Name);                       //函数名称为可执行字符串项中定义的执行字符串名称  
  104.                 code.Append("{ ");                                  //添加函数开始括号
  105.                 if (item.ReturnType.Name == "Void")
  106.                 {
  107.                     code.AppendFormat("{0};", item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值  
  108.                 }
  109.                 else
  110.                 {
  111.                     code.AppendFormat("return ({0});", item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值  
  112.                 }
  113.                 code.Append("}\n");                                 //添加函数结束括号  
  114.             }
  115.             code.Append("} }");                                 //添加类结束和命名空间结束括号  
  116.  
  117.             //得到编译器实例的返回结果  
  118.             CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
  119.  
  120.             if (cr.Errors.HasErrors)                            //如果有错误  
  121.             {
  122.                 StringBuilder error = new StringBuilder();          //创建错误信息字符串  
  123.                 error.Append("编译有错误的表达式: ");                //添加错误文本  
  124.                 foreach (CompilerError err in cr.Errors)            //遍历每一个出现的编译错误  
  125.                 {
  126.                     error.AppendFormat("{0}\n", err.ErrorText);     //添加进错误文本,每个错误后换行  
  127.                 }
  128.                 throw new Exception("编译错误: " + error.ToString());//抛出异常  
  129.             }
  130.             Assembly a = cr.CompiledAssembly;                       //获取编译器实例的程序集  
  131.             _Compiled = a.CreateInstance("EvalGuy._Evaluator");     //通过程序集查找并声明 EvalGuy._Evaluator 的实例  
  132.         }
  133.         #endregion
  134.  
  135.         #region 公有成员
  136.         /// <summary>  
  137.         /// 执行字符串并返回整型值  
  138.         /// </summary>  
  139.         /// <param name="name">执行字符串名称</param>  
  140.         /// <returns>执行结果</returns>  
  141.         public int EvaluateInt(string name)
  142.         {
  143.             return (int)Evaluate(name);
  144.         }
  145.         /// <summary>  
  146.         /// 执行字符串并返回字符串型值  
  147.         /// </summary>  
  148.         /// <param name="name">执行字符串名称</param>  
  149.         /// <returns>执行结果</returns>  
  150.         public string EvaluateString(string name)
  151.         {
  152.             return (string)Evaluate(name);
  153.         }
  154.         /// <summary>  
  155.         /// 执行字符串并返回布尔型值  
  156.         /// </summary>  
  157.         /// <param name="name">执行字符串名称</param>  
  158.         /// <returns>执行结果</returns>  
  159.         public bool EvaluateBool(string name)
  160.         {
  161.             return (bool)Evaluate(name);
  162.         }
  163.         /// <summary>  
  164.         /// 执行字符串并返 object 型值  
  165.         /// </summary>  
  166.         /// <param name="name">执行字符串名称</param>  
  167.         /// <returns>执行结果</returns>  
  168.         public object Evaluate(string name)
  169.         {
  170.             MethodInfo mi = _Compiled.GetType().GetMethod(name);//获取 _Compiled 所属类型中名称为 name 的方法的引用  
  171.             return mi.Invoke(_Compiled, null);                  //执行 mi 所引用的方法  
  172.         }
  173.  
  174.         public void EvaluateVoid(string name)
  175.         {
  176.             MethodInfo mi = _Compiled.GetType().GetMethod(name);//获取 _Compiled 所属类型中名称为 name 的方法的引用  
  177.             mi.Invoke(_Compiled, null);                  //执行 mi 所引用的方法  
  178.         }
  179.  
  180.         #endregion
  181.  
  182.         #region 静态成员
  183.         /// <summary>  
  184.         /// 执行表达式并返回整型值  
  185.         /// </summary>  
  186.         /// <param name="code">要执行的表达式</param>  
  187.         /// <returns>运算结果</returns>  
  188.         static public int EvaluateToInteger(string code)
  189.         {
  190.             Evaluator eval = new Evaluator(typeof(int), code, staticMethodName);//生成 Evaluator 类的对像  
  191.             return (int)eval.Evaluate(staticMethodName);                        //执行并返回整型数据  
  192.         }
  193.         /// <summary>  
  194.         /// 执行表达式并返回字符串型值  
  195.         /// </summary>  
  196.         /// <param name="code">要执行的表达式</param>  
  197.         /// <returns>运算结果</returns>  
  198.         static public string EvaluateToString(string code)
  199.         {
  200.             Evaluator eval = new Evaluator(typeof(string), code, staticMethodName);//生成 Evaluator 类的对像  
  201.             return (string)eval.Evaluate(staticMethodName);                     //执行并返回字符串型数据  
  202.         }
  203.         /// <summary>  
  204.         /// 执行表达式并返回布尔型值  
  205.         /// </summary>  
  206.         /// <param name="code">要执行的表达式</param>  
  207.         /// <returns>运算结果</returns>  
  208.         static public bool EvaluateToBool(string code)
  209.         {
  210.             Evaluator eval = new Evaluator(typeof(bool), code, staticMethodName);//生成 Evaluator 类的对像  
  211.             return (bool)eval.Evaluate(staticMethodName);                       //执行并返回布尔型数据  
  212.         }
  213.         /// <summary>  
  214.         /// 执行表达式并返回 object 型值  
  215.         /// </summary>  
  216.         /// <param name="code">要执行的表达式</param>  
  217.         /// <returns>运算结果</returns>  
  218.         static public object EvaluateToObject(string code)
  219.         {
  220.             Evaluator eval = new Evaluator(typeof(object), code, staticMethodName);//生成 Evaluator 类的对像  
  221.             return eval.Evaluate(staticMethodName);                             //执行并返回 object 型数据  
  222.         }
  223.  
  224.         /// <summary>  
  225.         /// 执行表达式并返回 void 空值  
  226.         /// </summary>  
  227.         /// <param name="code">要执行的表达式</param>  
  228.         static public void EvaluateToVoid(string code)
  229.         {
  230.             Evaluator eval = new Evaluator(typeof(void), code, staticMethodName);//生成 Evaluator 类的对像  
  231.             eval.EvaluateVoid(staticMethodName);                             //执行并返回 object 型数据  
  232.         }
  233.  
  234.         #endregion
  235.  
  236.         #region 私有成员
  237.         /// <summary>  
  238.         /// 静态方法的执行字符串名称  
  239.         /// </summary>  
  240.         private const string staticMethodName = "ExecuteBtnCommand";
  241.         /// <summary>  
  242.         /// 用于动态引用生成的类,执行其内部包含的可执行字符串  
  243.         /// </summary>  
  244.         object _Compiled = null;
  245.         #endregion
  246.     }
  247.     /// <summary>  
  248.     /// 可执行字符串项(即一条可执行字符串)  
  249.     /// </summary>  
  250.     public class EvaluatorItem
  251.     {
  252.         /// <summary>  
  253.         /// 返回值类型  
  254.         /// </summary>  
  255.         public Type ReturnType;
  256.         /// <summary>  
  257.         /// 执行表达式  
  258.         /// </summary>  
  259.         public string Expression;
  260.         /// <summary>  
  261.         /// 执行字符串名称  
  262.         /// </summary>  
  263.         public string Name;
  264.         /// <summary>  
  265.         /// 可执行字符串项构造函数  
  266.         /// </summary>  
  267.         /// <param name="returnType">返回值类型</param>  
  268.         /// <param name="expression">执行表达式</param>  
  269.         /// <param name="name">执行字符串名称</param>  
  270.         public EvaluatorItem(Type returnType, string expression, string name)
  271.         {
  272.             ReturnType = returnType;
  273.             Expression = expression;
  274.             Name = name;
  275.         }
  276.     }
  277. }
  278.  
  279.  
  280. //csharp/6356

回复 "C#动态编译,实现按钮功能动态配置"

这儿你可以回复上面这条便签

captcha