iT邦幫忙

DAY 5
2

c#應用系列 第 5

C#應用(5)使用Eval

Eval 是一種動態引用程式碼的技術
相關技術:
*CodeDomProvider Class
*CompilerParameters Class
*Assembly Class

回目錄
* 檔案 Evaluates.cs

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Text;
using System.Reflection;

namespace System.CodeDom.Compiler
{   
    /// <summary>
    /// 程式語言種類
    /// </summary>
    public enum LangType {
        CSharp,
        VisualBasic
    }

    public class Evaluates
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="type">程式語言種類</param>
        /// <param name="code">封裝前的原始程式碼</param>
        /// <param name="UsingNamespace">使用組件的命名空間</param>
        /// <param name="NamespaceName">執行時的命名空間</param>
        /// <param name="ClassName">執行時的類別名稱</param>
        /// <param name="MethodName">執行時的函數名稱</param>
        /// <param name="ParamsForamt">執行時的參數格式定義</param>
        /// <returns></returns>
        public static string GetEvalSource(
            LangType type,
            string code,
            string [] UsingNamespace = null,
            string NamespaceName = "DynameEval",
            string ClassName = "Class1",
            string MethodName = "Exec",
            string ParamsForamt = "")
        {
            StringBuilder sb = new StringBuilder();

            switch (type)
            {
                case LangType.CSharp:
                    {
                        sb.Append("using System;\n");
                        if (UsingNamespace != null)
                        {
                            foreach (string refUsing in UsingNamespace)
                            {
                                sb.AppendFormat("using {0};\n", refUsing);
                            }
                        }
                        sb.AppendFormat("namespace {0} { \n", NamespaceName);
                        sb.AppendFormat("public class {0} { \n", ClassName);
                        sb.AppendFormat("public object {0}({1}){\n", MethodName, ParamsForamt);
                        if (code.IndexOf("return") >=0)
                        {
                            sb.AppendFormat("{0}; \n", code);
                        }
                        else 
                        {
                            sb.AppendFormat("return {0}; \n", code);
                        }
                        sb.Append("} \n");
                        sb.Append("} \n");
                        sb.Append("}\n");
                    }
                    break;
                case LangType.VisualBasic:
                    {
                        sb.Append("Imports System\n");
                        sb.Append("Imports Microsoft.VisualBasic\n");
                        if (UsingNamespace != null)
                        {
                            foreach (string refUsing in UsingNamespace)
                            {
                                sb.AppendFormat("Imports {0}\n", refUsing);
                            }
                        }
                        sb.AppendFormat("Namespace {0}\n", NamespaceName);
                        sb.AppendFormat("Public Class {0}\n", ClassName);
                        sb.AppendFormat("Public Function {0}({1}) As Object\n", MethodName, ParamsForamt);
                        if (code.IndexOf("Return") >= 0)
                        {
                            sb.AppendFormat("{0} \n", code);
                        }
                        else
                        {
                            sb.AppendFormat("Return DirectCast({0}, Object) \n", code);
                        }
                        sb.Append("End Function\n");
                        sb.Append("End Class\n");
                        sb.Append("End Namespace\n");
                    }
                    break;
            }

            return sb.ToString();
        }
        /// <summary>
        /// 從記憶體中的原始程式碼字串, 進行編譯與執行
        /// </summary>
        /// <param name="type">程式語言種類</param>
        /// <param name="ErrorText">傳出編譯錯誤的原因</param>
        /// <param name="code">原始程式碼</param>
        /// <param name="ReferencedAssemblies">執行時需要載入的DLL檔, 不使用則用 null</param>
        /// <param name="InstanceName">類別名稱(含命名空間)</param>
        /// <param name="MethodName">要執行的函數名稱</param>
        /// <param name="oParams">執行時傳入參數的陣列, 如果不使用傳入參數則用 null</param>
        /// <returns>傳出執行的傳回值</returns>
        public static object EvalFromSource(
            LangType type,
            ref string ErrorText,
            string code,
            string[] ReferencedAssemblies = null,
            string InstanceName = "DynameEval.Class1",
            string MethodName = "Exec",
            object[] oParams = null)
        {
            string language = "";
            CodeDomProvider provider = null;

            switch (type)
            {
                case LangType.CSharp:
                    language = "CSharp";
                    break;
                case LangType.VisualBasic:
                    language = "VisualBasic";
                    break;
            }

            if (CodeDomProvider.IsDefinedLanguage(language))
            {
                provider = CodeDomProvider.CreateProvider(language);
            }

            if (provider == null)
            {
                ErrorText = string.Format("無法載入{0}的CodeDomProvider", language);
                return null;
            }

            CompilerParameters cp = new CompilerParameters();

            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Core.dll");
            if (type == LangType.VisualBasic)
            {
                cp.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
            }
            if (ReferencedAssemblies != null)
            {
                foreach (string refDll in ReferencedAssemblies)
                {
                    cp.ReferencedAssemblies.Add(refDll);
                }
            }

            cp.CompilerOptions = "/t:library";
            cp.GenerateInMemory = true;

            // Invoke compilation of the source code.
            CompilerResults cr = provider.CompileAssemblyFromSource(cp, code);
            if (cr.Errors.Count > 0)
            {
                ErrorText = cr.Errors[0].ErrorText;
                return null;
            }

            ErrorText = "";
            Assembly a = cr.CompiledAssembly;
            object o = a.CreateInstance(InstanceName);
            Type t = o.GetType();
            MethodInfo mi = t.GetMethod(MethodName);
            object s = mi.Invoke(o, oParams);
            return s;
        }

        /// <summary>
        /// 從程式碼的檔案, 進行編譯與執行
        /// </summary>
        /// <param name="type">程式語言種類</param>
        /// <param name="ErrorText">傳出編譯錯誤的原因</param>
        /// <param name="file">原始程式檔案</param>
        /// <param name="ReferencedAssemblies">執行時需要載入的DLL檔, 不使用則用 null</param>
        /// <param name="InstanceName">類別名稱(含命名空間)</param>
        /// <param name="MethodName">要執行的函數名稱</param>
        /// <param name="oParams">執行時傳入參數的陣列, 如果不使用傳入參數則用 null</param>
        /// <returns>傳出執行的傳回值</returns>
        public static object EvalFromFile(
            LangType type,
            ref string ErrorText,
            string file,
            string[] ReferencedAssemblies = null,
            string InstanceName = "DynameEval.Class1",
            string MethodName = "Exec",
            object[] oParams = null)
        {
            string language = "";
            CodeDomProvider provider = null;

            switch (type)
            {
                case LangType.CSharp:
                    language = "CSharp";
                    break;
                case LangType.VisualBasic:
                    language = "VisualBasic";
                    break;
            }

            if (CodeDomProvider.IsDefinedLanguage(language))
            {
                provider = CodeDomProvider.CreateProvider(language);
            }

            if (provider == null)
            {
                ErrorText = string.Format("無法載入{0}的CodeDomProvider", language);
                return null;
            }

            CompilerParameters cp = new CompilerParameters();

            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Core.dll");
            if (type == LangType.VisualBasic)
            {
                cp.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
            }
            if (ReferencedAssemblies != null)
            {
                foreach (string refDll in ReferencedAssemblies)
                {
                    cp.ReferencedAssemblies.Add(refDll);
                }
            }

            cp.CompilerOptions = "/t:library";
            cp.GenerateInMemory = true;

            // Invoke compilation of the source code.
            CompilerResults cr = provider.CompileAssemblyFromFile(cp, file);
            if (cr.Errors.Count > 0)
            {
                ErrorText = cr.Errors[0].ErrorText;
                return null;
            }

            ErrorText = "";
            Assembly a = cr.CompiledAssembly;
            object o = a.CreateInstance(InstanceName);
            Type t = o.GetType();
            MethodInfo mi = t.GetMethod(MethodName);
            object s = mi.Invoke(o, oParams);
            return s;
        }
    }
}

上一篇
C#應用(4)jqGrid的條件式搜尋
下一篇
C#應用(6)加密與解密,以及雜湊值
系列文
c#應用13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
wilson1966
iT邦研究生 2 級 ‧ 2013-09-22 07:28:40

讚! 進階級程度

我要留言

立即登入留言