C#中動態執行代碼,執行字符串中的代碼

代碼主要是從別的地方扒過來的,自己做過實驗,可行

using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;


namespace EvalGuy
{
    /// <summary> 
    /// 本類用來將字符串轉爲可執行文本並執行 
    /// </summary> 
    public class Evaluator
    {
        #region 構造函數
        /// <summary> 
        /// 可執行串的構造函數 
        /// </summary> 
        /// <param name="items"> 
        /// 可執行字符串數組 
        /// </param> 
        public Evaluator(EvaluatorItem[] items)
        {
            ConstructEvaluator(items);      //調用解析字符串構造函數進行解析 
        }
        /// <summary> 
        /// 可執行串的構造函數 
        /// </summary> 
        /// <param name="returnType">返回值類型</param> 
        /// <param name="expression">執行表達式</param> 
        /// <param name="name">執行字符串名稱</param> 
        public Evaluator(Type returnType, string expression, string name)
        {
            //創建可執行字符串數組 
            EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
            ConstructEvaluator(items);      //調用解析字符串構造函數進行解析 
        }
        /// <summary> 
        /// 可執行串的構造函數 
        /// </summary> 
        /// <param name="item">可執行字符串項</param> 
        
        public Evaluator(EvaluatorItem item)
        {
            EvaluatorItem[] items = { item };//將可執行字符串項轉爲可執行字符串項數組 
            ConstructEvaluator(items);      //調用解析字符串構造函數進行解析 
        }
        /// <summary> 
        /// 解析字符串構造函數 
        /// </summary> 
        /// <param name="items">待解析字符串數組</param> 
        private void ConstructEvaluator(EvaluatorItem[] items)
        {
            //創建C#編譯器實例 
            ICodeCompiler comp = (new CSharpCodeProvider().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; \n");
            code.Append("using System.Data; \n");
            code.Append("using System.Data.SqlClient; \n");
            code.Append("using System.Data.OleDb; \n");
            code.Append("using System.Xml; \n");


            code.Append("namespace EvalGuy { \n");                  //生成代碼的命名空間爲EvalGuy,和本代碼一樣 


            code.Append(" public class _Evaluator { \n");          //產生 _Evaluator 類,所有可執行代碼均在此類中運行 
            foreach (EvaluatorItem item in items)               //遍歷每一個可執行字符串項 
            {
                code.AppendFormat("    public {0} {1}(object c_object) ",          //添加定義公共函數代碼 
                                  item.ReturnType.Name,             //函數返回值爲可執行字符串項中定義的返回值類型 
                                  item.Name);                        //函數名稱爲可執行字符串項中定義的執行字符串名稱 


                code.Append("{ ");                                  //添加函數開始括號 
                //code.AppendFormat("return ({0});", item.Expression);//添加函數體,返回可執行字符串項中定義的表達式的值
                code.AppendFormat(item.Expression);//添加函數體,返回可執行字符串項中定義的表達式的值
                code.Append("}\n");                                 //添加函數結束括號 
            }
            code.Append(" }}");  // code.Append("} }")                              //添加類結束和命名空間結束括號 


            //得到編譯器實例的返回結果 
            CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());


            if (cr.Errors.HasErrors)                            //如果有錯誤 
            {
                StringBuilder error = new StringBuilder();          //創建錯誤信息字符串 
                error.Append("編譯有錯誤的表達式: ");                //添加錯誤文本 
                foreach (CompilerError err in cr.Errors)            //遍歷每一個出現的編譯錯誤 
                {
                    error.AppendFormat("{0}\n", err.ErrorText);     //添加進錯誤文本,每個錯誤後換行 
                }
                throw new Exception("編譯錯誤: " + error.ToString());//拋出異常 
            }
            Assembly a = cr.CompiledAssembly;                       //獲取編譯器實例的程序集 
            _Compiled = a.CreateInstance("EvalGuy._Evaluator");     //通過程序集查找並聲明 EvalGuy._Evaluator 的實例 
        }
        #endregion


        #region 公有成員
        /// <summary> 
        /// 執行字符串並返回整型值 
        /// </summary> 
        /// <param name="name">執行字符串名稱</param> 
        /// <returns>執行結果</returns> 
        public int EvaluateInt(string name, object c_object)
        {
            return (int)Evaluate(name, c_object);
        }
        /// <summary> 
        /// 執行字符串並返回字符串型值 
        /// </summary> 
        /// <param name="name">執行字符串名稱</param> 
        /// <returns>執行結果</returns> 
        public string EvaluateString(string name, object c_object)
        {
            return (string)Evaluate(name, c_object);
        }
        /// <summary> 
        /// 執行字符串並返回布爾型值 
        /// </summary> 
        /// <param name="name">執行字符串名稱</param> 
        /// <returns>執行結果</returns> 
        public bool EvaluateBool(string name, object c_object)
        {
            return (bool)Evaluate(name, c_object);
        }
        /// <summary> 
        /// 執行字符串並返 object 型值 
        /// </summary> 
        /// <param name="name">執行字符串名稱</param> 
        /// <returns>執行結果</returns> 
        public object Evaluate(string name, object c_object)
        {
            MethodInfo mi = _Compiled.GetType().GetMethod(name);//獲取 _Compiled 所屬類型中名稱爲 name 的方法的引用 
            object[] _object = { c_object };
            return mi.Invoke(_Compiled, _object);                  //執行 mi 所引用的方法
        }
        #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)
        {
            this.ReturnType = returnType;
            this.Expression = expression;
            this.Name = name;
        }
    }
}



使用例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
//using System.Math have collected to System namespace


namespace calculator_final
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            double a = 50 % 4;//mod
            double b = System.Math.Sqrt(8);//sqrt
            double c = System.Math.Sin(3);//power


            string teststring = "1+2+(3+3)*5mod5+2*mod(3,2)";




            
            object result = new DataTable().Compute(a.ToString()+"+2*(-3+4.0)"+"+"+b.ToString()+"*"+c.ToString(), null);
            input_box.Text=result.ToString();




        }
        /*
        private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
        {


        }*/


        


        private void button_sin_Click(object sender, RoutedEventArgs e)
        {
            input_box.Text = "sin";
            float[] a=new float[5]{1,2,3,4,5};
            float sum = statistic_or_other.sum(a, 5);
            
            System.Math.Sin(sum);
        }


        private void button_avg_Click(object sender, RoutedEventArgs e)
        {
            
            float[] a = new float[5] { 1, 2, 3, 4, 5 };
            float sum = statistic_or_other.sum(a, 5);
            input_box.Text = sum.ToString();
            
        }


     
    }






    public partial class statistic_or_other
    {




        public statistic_or_other()
        {
 
         
        }


        static public float sum(float[] a, int len)
        {
            float sum = 0;
            for (int i = 0; i < len; i++)
                sum += a[i];
            return sum;


        }


        static public float avg(float[] a, int len)
        {
            float avg = 0;
       
            for (int i = 0; i < len; i++)
                avg += a[i];
            avg /= len;
            return avg;
        
        }
        static public float var(float[] a, int len)
        {
            float var = 0, sum = 0;


            for (int i = 0; i < len; i++)
                sum += a[i];
            sum/=len;
            for (int i = 0; i < len; i++)
                var += (a[i] - sum) * (a[i] - sum);
            var /= len;
            return var;
            
        }
        static public float varp(float[] a, int len)
        {


            return len / (len - 1) * var(a, len);
        }
        static public float stdev(float[] a, int len)
        {


            return (float)System.Math.Sqrt(var(a, len));


        }
        static public float stdevp(float[] a, int len)
        {
            return (float)System.Math.Sqrt(varp(a, len));
        
        }


        static public int fact(int n)
        {
            if (n < 0)
                MessageBox.Show("error", "out of the effective boundary ,please input a interger eauqal to or greater than 0");
            if (n == 0 || n == 1)
                return 1;
            else
                return n * fact(n - 1);


        
        }


        static public float sparse_mod(string s)
        {
            string teststr = "1+2+(3+3)*5mod5+2*mod(3,2)";
            int index=0;
            l=teststr.Length;
            int[]a= new int[5];
            bool search=true;
            int i =0;
            while (search && (i >=5))
            {
                index = teststr.IndexOf("mod", index);
                if (index == -1)
                    search = false;
                else
                    a[i++] = index;
                index++;
            }
            for (int j = 0; j < i - 1; j++)
            {
                try
                {
                    substr = teststr.Substring(a[j] - 1, 1);
                }
                catch
                {}
            


            
            }






 
                










        
        
        }


    
    
    }


}


代碼有點亂,修改與調試時打亂了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章