c# EVAL 动态 执行 代码 .net 执...

148 篇文章 1 订阅
 using System;
using System.Data;
using System.Configuration;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Text;
using System.Reflection;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;

namespace CommandDebugger
{
    /// <summary>
    /// C#代码执行器,提供动态执行C#代码
    /// </summary>
    public class Evaluator
    {
        private static CSharpCodeProvider cCodeProder = null;
        private static CompilerParameters compPars = null;
        private static CompilerResults compResult = null;
        private static Regex rexLastCode = new Regex(@"(print:).+;\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); //用于搜索最后一条代码的位置

        static Evaluator()
        {
            cCodeProder = new CSharpCodeProvider();
        }

        /// <summary>
        /// 执行指定的代码
        /// </summary>
        /// <param name="strCodes"></param>
        /// <returns></returns>
        public static string Eval(string strCodes, out string strErrText)
        {
            #region 编译代码
            strErrText = InitCompile(ref strCodes);
            if (strErrText != null) return null;
            try
            {
                compResult = cCodeProder.CompileAssemblyFromSource(compPars, new string[] { strCodes });
            }
            catch (NotImplementedException nie)
            {
                strErrText = nie.Message;
                return null;
            }

            if (compResult.Errors.HasErrors)
            {
                StringBuilder sbErrs = new StringBuilder(strCodes + System.Environment.NewLine);
                sbErrs.Append("您所提供的C#代码中存在语法错误!" + System.Environment.NewLine );
                foreach (CompilerError err in compResult.Errors)
                {
                    sbErrs.AppendFormat("{0},{1}" + System.Environment.NewLine, err.ErrorNumber, err.ErrorText);
                }
                strErrText = sbErrs.ToString();
                return null;
            }
            #endregion

            Assembly assembly = compResult.CompiledAssembly;
            object prgInsl = assembly.CreateInstance("System._ClassEvaluatorCompiler");
            MethodInfo medInfo = prgInsl.GetType().GetMethod("PrintResult");
            string strRetn;
            try
            {
                strRetn = medInfo.Invoke(prgInsl, null).ToString();
                return strRetn;
            }
            catch(Exception exMsg)
            {
                strErrText = exMsg.Message;
                return null;
            }
        }

        /// <summary>
        /// 预编译代码
        /// </summary>
        /// <param name="strCodes">待编译的源代码</param>
        /// <returns>如果错误则返回错误消息</returns>
        private static string InitCompile(ref string strCodes)
        {
            List<string> lstRefs = new List<string>();//代码字符串中的include引用程序集------未使用

            List<string> lstUsings = new List<string>();//代码字符串中的using引用命名空间


            #region 分离引用的程序集与命名空间
            int point = 0;
            string strTemp;
            char[] cCodes = strCodes.ToCharArray();
            for (int i = 0; i < cCodes.Length; ++i)
            {
                if (cCodes[i] == '\n' || (cCodes[i] == '\r' && cCodes[i + 1] == '\n'))
                {
                    strTemp = strCodes.Substring(point, i - point);
                    if (strTemp.TrimStart(new char[] { ' ' }).StartsWith("using "))
                    {
                        strTemp = strTemp.Substring(6).Trim();
                        if (!lstUsings.Contains(strTemp))
                        {
                            lstUsings.Add(strTemp);
                        }
                        else
                        {
                            return "预编译失败,代码中不允许包含重复命名空间导入。"+System.Environment.NewLine+"using " + strTemp;
                        }
                        point = cCodes[i] == '\n' ? i + 1 : i + 2;
                        ++i;
                    }
                    else if (strTemp.TrimStart(new char[] { ' ' }).StartsWith("include "))
                    {
                        strTemp = strTemp.Substring(8).Trim().ToLower();
                        if (!lstRefs.Contains(strTemp))
                        {
                            lstUsings.Add(strTemp);
                        }
                        else
                        {
                            return "预编译失败,代码中不允许包含重复的程序集引用。"+System.Environment.NewLine+"include " + strTemp;
                        }
                        point = cCodes[i] == '\n' ? i + 1 : i + 2;
                        ++i;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            strCodes = strCodes.Substring(point);
            #endregion

            #region 初始化编译参数
            if (compPars == null)
            {
                compPars = new CompilerParameters();
                compPars.GenerateExecutable = false;
                compPars.GenerateInMemory = true;
            }
            //string workDir = System.Web.HttpContext.Current.Server.MapPath("~") + "Bin\\";
            //string workDir = System.Environment.CurrentDirectory;
            compPars.ReferencedAssemblies.Clear();
            compPars.ReferencedAssemblies.Add("system.dll");
            compPars.ReferencedAssemblies.Add("system.data.dll");
            compPars.ReferencedAssemblies.Add("system.xml.dll");

            //compPars.ReferencedAssemblies.Add(workDir + "BLL.dll");
            //compPars.ReferencedAssemblies.Add(workDir + "Component.dll");
            //compPars.ReferencedAssemblies.Add(workDir + "Model.dll");
            //compPars.ReferencedAssemblies.Add(workDir + "Utility.dll");

            foreach (string str in lstRefs)
            {
                compPars.ReferencedAssemblies.Add(str);
            }
            #endregion

            StringBuilder sbRetn = new StringBuilder();

            #region 生成代码模板
            ///*为代码添加return 语句*/
            Match match = rexLastCode.Match(strCodes);
            if (match.Success)
            {
                strCodes = string.Format("{0}\r\nreturn {1}", strCodes.Substring(0, match.Groups[1].Index), strCodes.Substring(match.Groups[1].Index + match.Groups[1].Length));
            }
            else
            {
                strCodes = "return " + strCodes.Trim();//把要运行的代码字符串作为返回值---作为输出 - 显示运行的字符串源码
            }

            /*拼接代码*/
            foreach (string str in lstUsings)
            {
                sbRetn.AppendLine("using " + str);
            }
            sbRetn.AppendLine("namespace System{");
            sbRetn.AppendLine("public class _ClassEvaluatorCompiler{");
            sbRetn.AppendLine("public static object PrintResult(){");
            sbRetn.AppendLine(strCodes);
            sbRetn.AppendLine("}}}");
            #endregion
            strCodes = sbRetn.ToString();
            return null;
        }


    }



    public class ProgramTest
    {
        static void Main(string[] args)
        {
            string error = string.Empty;
            string res = string.Empty;
            string code = "1+1/0;";

            //c# EVAL 动态 执行 代码 .net 执行 字符串 代码
            res = CommandDebugger.Evaluator.Eval(code, out error);


            if (!string.IsNullOrEmpty(error))
            {
                Console.WriteLine(error);
            }
            else
            {
                Console.WriteLine("执行结果为:" + res);
            }
        }
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值