none
程式碼執行 RRS feed

  • 問題

  • 如果以下的class, 我想要不產生檔案, 就直接編譯後執行的話
    該怎麼改?
    想做出類似JavaScript的Eval() 的可程式碼執行的效果

    Code Snippet

    using System;
    using System.CodeDom.Compiler;

    namespace dotNetLang
    {
    //編譯的來源? 檔案或記憶體(放在String[] 中)
    enum CodeFrom
    {
    Files,
    Sources
    };

    class CSharpCode
    {
    public static void Compile(string strOutputFile, string[] CodeSrc, CodeFrom FromType, string strMainClass, bool IsCompiledToExec)
    {
    using (Microsoft.CSharp.CSharpCodeProvider CodeProvider = new Microsoft.CSharp.CSharpCodeProvider())
    {
    CompilerParameters param = new CompilerParameters();

    param.OutputAssembly = strOutputFile;


    //預設引用mscorlib.dll
    param.ReferencedAssemblies.Add(

    System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + "mscorlib.dll");

    //程式的入口的類別名稱
    if (!String.IsNullOrEmpty(strMainClass))
    param.MainClass = strMainClass;

    //宣告編譯成exe檔
    param.GenerateExecutable = true;

    //編譯程式碼
    CompilerResults results;

    if (FromType == CodeFrom.Sources)
    results = CodeProvider.CompileAssemblyFromSource(param, CodeSrc);
    else
    results = CodeProvider.CompileAssemblyFromFile(param, CodeSrc);



    //如果沒有編譯錯誤,與IsCompiledToExec為true, 就跑執行
    if ((results.Errors.Count == 0) &&
    (IsCompiledToExec == true))
    {
    AppDomain domain = AppDomain.CreateDomain("Compiled App");
    domain.ExecuteAssembly(results.PathToAssembly);
    }
    }
    }
    }
    }


    2008年11月12日 上午 04:24

解答

  • Eval()參考這篇
     
     
    其中
    Code Snippet
    private static readonly string _jscriptSource = @"class Evaluator { public function Eval(expr : String) : String { return eval(expr); } }";

     

    改成

    Code Snippet

    private static readonly string _jscriptSource = @"class Evaluator { public function Eval(expr : String) : Object { return eval(expr); } }";

     

     

    可以正確的接收到計算後的型別
     
     
    另外幫你改好
    Code Snippet
    using System;
    using System.CodeDom.Compiler;
    using System.Reflection;
     
    namespace dotNetLang
    {
        //編譯的來源? 檔案或記憶體(放在String[] 中)
        enum CodeFrom
        {
            Files,
            Sources
        }
     
        class CSharpCode
        {
            public static Assembly Compile(string[] CodeSrc, CodeFrom FromType, string strMainClass, bool IsCompiledToExec)
            {
                using (Microsoft.CSharp.CSharpCodeProvider CodeProvider = new Microsoft.CSharp.CSharpCodeProvider())
                {
                    CompilerParameters param = new CompilerParameters();
                   
                    //輸出在記憶體
                    param.GenerateInMemory = true;
     
                    //預設引用mscorlib.dll
                    param.ReferencedAssemblies.Add(
                    System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + "mscorlib.dll");
     
                    //程式的入口的類別名稱
                    if (strMainClass != null)
                        param.MainClass = strMainClass;
     
                    //宣告編譯成可執行檔 (只有可執行檔才有進入點)
                    param.GenerateExecutable = true;
     
                    //編譯程式碼
                    CompilerResults results;
     
                    if (FromType == CodeFrom.Sources)
                        results = CodeProvider.CompileAssemblyFromSource(param, CodeSrc);
                    else
                        results = CodeProvider.CompileAssemblyFromFile(param, CodeSrc);
     
     
     
                    //如果沒有編譯錯誤回傳該組件
                    if (results.Errors.HasErrors == false)
                        return results.CompiledAssembly;
                    else
                        return null;
                }
            }
        }
    }

     

     

    呼叫Compile(...)會回傳一個Assembly
    在呼叫Assembly的進入點就可以執行了
    Assembly a = Compile(...);
    a.EntryPoint.Invoke(null,null); //如果Main()有參數的話 ,要改掉第2個null
    2008年11月12日 上午 06:21

所有回覆

  • Eval()參考這篇
     
     
    其中
    Code Snippet
    private static readonly string _jscriptSource = @"class Evaluator { public function Eval(expr : String) : String { return eval(expr); } }";

     

    改成

    Code Snippet

    private static readonly string _jscriptSource = @"class Evaluator { public function Eval(expr : String) : Object { return eval(expr); } }";

     

     

    可以正確的接收到計算後的型別
     
     
    另外幫你改好
    Code Snippet
    using System;
    using System.CodeDom.Compiler;
    using System.Reflection;
     
    namespace dotNetLang
    {
        //編譯的來源? 檔案或記憶體(放在String[] 中)
        enum CodeFrom
        {
            Files,
            Sources
        }
     
        class CSharpCode
        {
            public static Assembly Compile(string[] CodeSrc, CodeFrom FromType, string strMainClass, bool IsCompiledToExec)
            {
                using (Microsoft.CSharp.CSharpCodeProvider CodeProvider = new Microsoft.CSharp.CSharpCodeProvider())
                {
                    CompilerParameters param = new CompilerParameters();
                   
                    //輸出在記憶體
                    param.GenerateInMemory = true;
     
                    //預設引用mscorlib.dll
                    param.ReferencedAssemblies.Add(
                    System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + "mscorlib.dll");
     
                    //程式的入口的類別名稱
                    if (strMainClass != null)
                        param.MainClass = strMainClass;
     
                    //宣告編譯成可執行檔 (只有可執行檔才有進入點)
                    param.GenerateExecutable = true;
     
                    //編譯程式碼
                    CompilerResults results;
     
                    if (FromType == CodeFrom.Sources)
                        results = CodeProvider.CompileAssemblyFromSource(param, CodeSrc);
                    else
                        results = CodeProvider.CompileAssemblyFromFile(param, CodeSrc);
     
     
     
                    //如果沒有編譯錯誤回傳該組件
                    if (results.Errors.HasErrors == false)
                        return results.CompiledAssembly;
                    else
                        return null;
                }
            }
        }
    }

     

     

    呼叫Compile(...)會回傳一個Assembly
    在呼叫Assembly的進入點就可以執行了
    Assembly a = Compile(...);
    a.EntryPoint.Invoke(null,null); //如果Main()有參數的話 ,要改掉第2個null
    2008年11月12日 上午 06:21
  • 先整理到
    我那邊了

    http://www.player.idv.tw/prog/index.php?title=CSharpCode

    題外話:

    不過C#好像不像Win32時Call by Name 的DLL那樣
    可以動態卸載?

    如果用在Mud上
    當Chat的子系統未當
    而只要把NPC的子系統抽換成新的code的話
    如果Server端的主系統是一隻C#寫的exe檔
    各子系統是C#寫的dll檔
    那有可能不停止AP的前提下
    動態抽換子系統嗎?
    2008年11月12日 上午 10:04
  • 我有嘗試卸除EXE用Assembly的方法載入的DLL
    不過Assembly中的成員好像沒有可以清除的函數
    就算給他null賦值, GC也好像不會去清他
    所以這個我也沒成功過
     
     
     
    傳說
    函數導向的程式可以熱抽換
    正在執行中系統的任一一個函數
    2008年11月12日 下午 11:47