.net 动态编译,代码解释器

方案1.动态编译,2,script脚本,3.linq.expression
1.软件开放脚本录入容器(字符串),
2.动态编译成方法,
3.根据需要进行调用(可定义输入参数和返回类型) ,后期依据接口,开放式编程

 class DyncCompiler
    {
        /// <summary>
        /// 动态编译:解释器,返回方法体
        /// </summary>
        /// <param name="RTYPE">返回参数类型</param>
        /// <param name="para">参数:《参数名,参数类型》</param>
        /// <param name="methodstr">自定义方法体</param>
        /// <returns>方法信息,或委托</returns>
        public static MethodInfo Compiler(string RTYPE, Dictionary<string, string> para, string methodstr)
        {
            //CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
            CodeDomProvider cdp = CodeDomProvider.CreateProvider("C#");
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            cp.ReferencedAssemblies.Add("System.Linq.dll");
            cp.ReferencedAssemblies.Add("System.Data.dll");
            cp.ReferencedAssemblies.Add("System.Core.dll");
            cp.GenerateExecutable = false;  //false:生成dll ,true:生成exe
            cp.GenerateInMemory = true;
            //cp.OutputAssembly = "SimpleCompile.exe";
            string hello = "using System; " +
                           "using System.Windows.Forms; " +
                           "using System.Linq; " +
                           "using System.Data;" +
                           "using System.Collections.Generic;" +
                           "namespace HelloWorld " +
                           "{ " +
                           "    public class HelloWorld" +
                           "    {" +
                                    "public static " + (string.IsNullOrEmpty(RTYPE) ? "void" : RTYPE) + " SayHello (" + getpara(para) + " )" +
                                    "{" +
                                       methodstr +
                                    "}" +
                            "    }" +
                           "}";
            // 编译结果
            CompilerResults cr = cdp.CompileAssemblyFromSource(cp, hello);

            if (cr.Errors.HasErrors)
            {
                StringBuilder sb = new StringBuilder();
                foreach (CompilerError d in cr.Errors)
                    sb.AppendLine($"{d.Line},{d.ErrorNumber},{d.ErrorText}");
                throw new Exception(sb.ToString());
            }
            else
            {
                // 编译后的程序集
                Assembly ass = cr.CompiledAssembly;
                //创建类实例
                //ass.CreateInstance ("HelloWorld.HelloWorld")
                //获取类方法(固定名)
                Type type = ass.GetType("HelloWorld.HelloWorld");
                MethodInfo mi = type.GetMethod("SayHello");
                // mi.Invoke(null, new object[] { }); //方法体执行
                //Delegate del = mi.CreateDelegate(typeof(Action<string>));
                //del.DynamicInvoke();//委托执行
                return mi;
            }
        }
        /// <summary>
        /// 参数列表
        /// </summary>
        /// <param name="para"></param>
        /// <returns></returns>
        static string getpara(Dictionary<string, string> para)
        {
            if (para == null)
                return string.Empty;
            StringBuilder sb = new StringBuilder();
            foreach (var d in para)
            {
                sb.Append($" {d.Value}  {d.Key},");
            }
            return sb.ToString().TrimEnd(',');
        } 
        /// <summary>
        /// 内部执行:表达式  
        /// eg1:Evaluate<int>("(1+2)*3");
        /// eg2:Evaluate<int>("P1+P2*P3",4,5,6);
        /// eg3:DyncCompiler.Evaluate<int>(P1+P2*P3,x,y,z); int x=4,y=5,z=6
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="code">表达式代码</param>
        /// <param name="parameters">可选参数列表(按顺序P1,P2)</param>
        /// <returns></returns>
        public static T Evaluate<T>(string code, params object[] parameters)
        {
            if (!code.Contains("return"))
                code = "return " + code;
            if (!code.EndsWith(";"))
                code += ";";

            Dictionary<string, string> para = null;
            if (parameters.Count() > 0)
            {
                para = new Dictionary<string, string>();
                int i = 1;
                foreach (var p in parameters)
                {
                    para[$"P{i}"] = p.GetType().Name;
                    i++;
                }
            }
            var d = DyncCompiler.Compiler(typeof(T).Name, para, code);
            return (T)d.Invoke(null,  parameters ); //执行并返回整型数据  
        }      

winform 执行:

    //内部执行
    private void button6_Click(object sender, EventArgs e)
    {
       int x = 4, y = 5, z = 6;
       var n = DyncCompiler.Evaluate<int>(“P1+P2*p3”,x,y,z); 
       MessageBox.Show(n.ToString());
   }

    MethodInfo vd;
    private void button1_Click(object sender, EventArgs e)
    {
        try
        {                                     
            vd = DyncCompiler.Compiler(CmbReturnType.Text, para, richTextBox1.Text); //返回类型,参数字典,脚本内容
            button2.Enabled = vd != null;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "语法错误");
            vd = null;
            button2.Enabled = false;
        }
    }
    //执行
    private void button2_Click(object sender, EventArgs e)
    {    
        var n = vd.Invoke(null, new object[] { TxtInput1.Text, Txtinput2.Text });// vd.DynamicInvoke(TxtInput1.Text);
        if (n != null)
            MessageBox.Show(n.ToString());
    }

扩展方案2: 使用MSScriptControl
到软的网站上下载Windows Script Control,它是一个ActiveX® 控件,所以在.NET中使用我Interop了一下。下载安装完成后,新建一个C#的Windows应用程序项目,在解决方案资源管理器中选中引用节点,右键点击选择添加引用菜单,弹出添加引用对话框,单击浏览找到安装Windows Script Control的目录,选取msscript.ocx文件确定。那么在引用节点下会增加一个MSScriptControl组件
在这里插入图片描述

 //执行:事例
  private void button7_Click(object sender, EventArgs e)
  {
       var d = Js.init.Eval(textBox1.Text);
        if (d != null)
          MessageBox.Show(d.ToString());
  }
  //脚本语言
  public enum ScriptLanguage
    {
        JScript,
        VBscript,
        JavaScript
    }
  //脚本类
    public class Js
    {
        public static Js init = new Js();
        private Js()
        {
            msc = new MSScriptControl.ScriptControl();
            msc.AllowUI = true;
            msc.UseSafeSubset = true;
            Language = ScriptLanguage.JavaScript;
            ((DScriptControlSource_Event)this.msc).Error += new DScriptControlSource_ErrorEventHandler(ScriptEngine_Error);
        }
        MSScriptControl.ScriptControl msc;
        ScriptLanguage _Language;

        public ScriptLanguage Language
        {
            set
            {
                if (value == _Language)
                    return;
                msc.Language = value.ToString();
                _Language = value;
            }
        }
        public event Action<string> RunError;
        void ScriptEngine_Error()
        {
            err("脚本执行错误!");
        }
        void err(string errmsg)
        {
            if (RunError != null)
                RunError(errmsg);
        }
        /// <summary>
        /// 运行Eval方法
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>返回值object</returns>
        public object Eval(string expression)
        {
            try
            {
                return msc.Eval(expression);//计算表达式并返回结果。
            }
            catch (Exception ex)
            {
                err(ex.Message);
            }
            return null;
        }
        /// <summary>
        /// 运行Run方法
        /// </summary>
        /// <param name="mainFunctionName">入口函数名称</param>
        /// <param name="parameters">参数</param>
        /// <param name="codeBody">函数体</param>
        /// <returns>返回值object</returns>
        public object Run(string mainFunctionName, object[] parameters, string codeBody)
        {
            try
            {
                this.msc.AddCode(codeBody);//向模块添加指定代码。可多次调用 AddCode 方法。
                return msc.Run(mainFunctionName, ref parameters);//运行指定过程。
            }
            catch (Exception ex)
            {
                err(ex.Message);
            }
            return null;
        }
        public void Reset()
        {
            msc.Reset();//:放弃所有已经添加到 ScriptControl 中的 Script 代码和对象。
        }
    }

扩展方案3: System.Linq.Expressions

Expression表达式树(C#)

1.Expression d=  将字符串表达式转换成Expression();
2.LambdaExpression  lambda=Expression.Lambda(d); //  转为lambda 表达式
3.Delegate del=  lambda.Compile();  //转为委托类型
4.del.DynamicInvoke();//委托执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值