您好,登錄后才能下訂單哦!
這篇文章主要介紹了C#如何實現動態執行字符串腳本的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇C#如何實現動態執行字符串腳本文章都會有所收獲,下面我們一起來看看吧。
先來代碼
using System; using System.Data; using System.Configuration; using System.Text; using System.CodeDom.Compiler; using Microsoft.CSharp; using System.Reflection; using System.Collections.Generic; namespace 檢漏儀上位機 { /// <summary> /// 本類用來將字符串轉為可執行文本并執行 /// 從別處復制,勿隨意更改! /// </summary> public class Evaluator { #region 構造函數 /// <summary> /// 可執行串的構造函數 /// </summary> /// <param name="items"> /// 可執行字符串數組 /// </param> public Evaluator(EvaluatorItem[] items, Dictionary<string, string> listAssemblies = null) { ConstructEvaluator(items, listAssemblies); //調用解析字符串構造函數進行解析 } /// <summary> /// 可執行串的構造函數 /// </summary> /// <param name="returnType">返回值類型</param> /// <param name="expression">執行表達式</param> /// <param name="name">執行字符串名稱</param> public Evaluator(Type returnType, string expression, string name, Dictionary<string, string> listAssemblies = null) { //創建可執行字符串數組 EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) }; ConstructEvaluator(items, listAssemblies); //調用解析字符串構造函數進行解析 } public Evaluator(string allCode, string _namespace, string _class, List<string> listAssemblies = null) { ConstructEvaluatorByAllCode(allCode, _namespace, _class, listAssemblies); //調用解析字符串構造函數進行解析 } /// <summary> /// 可執行串的構造函數 /// </summary> /// <param name="item">可執行字符串項</param> public Evaluator(EvaluatorItem item, Dictionary<string, string> listAssemblies = null) { EvaluatorItem[] items = { item };//將可執行字符串項轉為可執行字符串項數組 ConstructEvaluator(items, listAssemblies); //調用解析字符串構造函數進行解析 } /// <summary> /// 解析字符串構造函數 /// </summary> /// <param name="items">待解析字符串數組</param> private void ConstructEvaluator(EvaluatorItem[] items, Dictionary<string, string> listAssemblies = null) { //創建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.ReferencedAssemblies.Add("System.Windows.Forms.dll"); //添加程序集 system.xml.dll 的引用 cp.GenerateExecutable = false; //不生成可執行文件 cp.GenerateInMemory = true; //在內存中運行 StringBuilder code = new StringBuilder(); //創建代碼串 if (listAssemblies != null) { foreach (var item in listAssemblies) { cp.ReferencedAssemblies.Add(item.Key); //添加程序集 引用 code.Append("using "+item.Value + "; \n"); } } /* * 添加常見且必須的引用字符串 */ 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("using System.Windows.Forms; \n"); code.Append("namespace EvalGuy { \n"); //生成代碼的命名空間為EvalGuy,和本代碼一樣 code.Append(" public class _Evaluator { \n"); //產生 _Evaluator 類,所有可執行代碼均在此類中運行 foreach (EvaluatorItem item in items) //遍歷每一個可執行字符串項 { code.AppendFormat(" public {0} {1}() ", //添加定義公共函數代碼 item.ReturnType == null ? "void" : item.ReturnType.Name, //函數返回值為可執行字符串項中定義的返回值類型 item.Name); //函數名稱為可執行字符串項中定義的執行字符串名稱 code.Append("{ "); //添加函數開始括號 if (item.ReturnType != null) code.AppendFormat("return ({0});", item.Expression);//添加函數體,返回可執行字符串項中定義的表達式的值 else { code.Append(item.Expression);//添加函數體,返回可執行字符串項中定義的表達式的值 } code.Append("}\n"); //添加函數結束括號 } 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 的實例 } private void ConstructEvaluatorByAllCode(string allcode, string _namespace, string _class, List<string> listAssemblies) { if (listAssemblies == null) { listAssemblies = new List<string>(); } //創建C#編譯器實例 ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler()); //編譯器的傳入參數 CompilerParameters cp = new CompilerParameters(); if (!listAssemblies.Contains("system.dll")) { listAssemblies.Add("system.dll"); listAssemblies.Add("system.data.dll"); listAssemblies.Add("system.xml.dll"); } foreach (var item in listAssemblies) { cp.ReferencedAssemblies.Add(item); } cp.GenerateExecutable = false; //不生成可執行文件 cp.GenerateInMemory = true; //在內存中運行 //得到編譯器實例的返回結果 CompilerResults cr = comp.CompileAssemblyFromSource(cp, allcode); 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($"{_namespace}.{_class}"); //通過程序集查找并聲明 EvalGuy._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 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> /// <param name="listAssemblies">需要引用到類庫,key:dll名稱,value:命名空間名稱</param> /// <returns>運算結果</returns> static public int EvaluateToInteger(string code, Dictionary<string, string> listAssemblies = null) { Evaluator eval = new Evaluator(typeof(int), code, staticMethodName, listAssemblies);//生成 Evaluator 類的對像 return (int)eval.Evaluate(staticMethodName); //執行并返回整型數據 } /// <summary> /// 執行表達式并返回字符串型值 /// </summary> /// <param name="code">要執行的表達式</param> /// <param name="listAssemblies">需要引用到類庫,key:dll名稱,value:命名空間名稱</param> /// <returns>運算結果</returns> static public string EvaluateToString(string code, Dictionary<string, string> listAssemblies = null) { Evaluator eval = new Evaluator(typeof(string), code, staticMethodName, listAssemblies);//生成 Evaluator 類的對像 return (string)eval.Evaluate(staticMethodName); //執行并返回字符串型數據 } /// <summary> /// 執行表達式并返回布爾型值 /// </summary> /// <param name="code">要執行的表達式</param> /// <param name="listAssemblies">需要引用到類庫,key:dll名稱,value:命名空間名稱</param> /// <returns>運算結果</returns> static public bool EvaluateToBool(string code, Dictionary<string, string> listAssemblies = null) { Evaluator eval = new Evaluator(typeof(bool), code, staticMethodName, listAssemblies);//生成 Evaluator 類的對像 return (bool)eval.Evaluate(staticMethodName); //執行并返回布爾型數據 } /// <summary> /// 執行表達式并返回 object 型值 /// </summary> /// <param name="code">要執行的表達式</param> /// <param name="listAssemblies">需要引用到類庫,key:dll名稱,value:命名空間名稱</param> /// <returns>運算結果</returns> static public object EvaluateToObject(string code, Dictionary<string, string> listAssemblies = null) { Evaluator eval = new Evaluator(typeof(object), code, staticMethodName, listAssemblies);//生成 Evaluator 類的對像 return eval.Evaluate(staticMethodName); //執行并返回 object 型數據 } /// <summary> /// 執行一個無返回式的代碼 /// </summary> /// <param name="code"></param> /// <param name="listAssemblies">需要引用到類庫,key:dll名稱,value:命名空間名稱</param> static public void EvaluateToVoid(string code, Dictionary<string, string> listAssemblies = null) { Evaluator eval = new Evaluator(null, code, staticMethodName, listAssemblies);//生成 Evaluator 類的對像 eval.Evaluate(staticMethodName); //執行并返回 object 型數據 } /// <summary> /// 執行一個全代碼 /// </summary> /// <param name="code">全代碼,包含命名空間引用,命名空間聲明,類聲明,函數聲明等</param> /// <param name="_namespace"></param> /// <param name="_class"></param> /// <param name="methodName">函數</param> /// <param name="listAssemblies">需要引用到類庫</param> public static void EvaluateByAllCode(string code, string _namespace, string _class, string methodName, List<string> listAssemblies = null) { Evaluator eval = new Evaluator(code, _namespace, _class, listAssemblies);//生成 Evaluator 類的對像 eval.Evaluate(methodName); } #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; } } }
調用一個無返回值的代碼,顯示一個提示框
Evaluator.EvaluateToVoid("MessageBox.Show(\"Test\");",new Dictionary<string, string>() { { "System.Windows.Forms.dll", "System.Windows.Forms" } });
調用一個計算返回整型
Evaluator.EvaluateToInteger("1+2*3");
調用一個全代碼
string str = @"using System; namespace a { public class b { public void c() { Console.WriteLine(1); } } }"; Evaluator.EvaluateByAllCode(str, "a", "b", "c");
功能就這么多
關于“C#如何實現動態執行字符串腳本”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“C#如何實現動態執行字符串腳本”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。