首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

簡易 C# 線上 IDE 實作(一):動態編譯與輸出捕獲架構

     編輯:關於C語言

核心問題

  1. 如何將網頁文字方塊的程式碼編譯執行?
  2. 如何捕獲 Console.Write/WriteLine 輸出並回傳網頁?

解決方案架構

Consoler - 自訂輸出收集器

public class Consoler
{
    public static Dictionary Outputs { get; set; } = new Dictionary();
    public List Output { get; private set; } = new List();
    public void Write(object s) => Output.Add(s.ToString());
    public void WriteLine(object s) => Output.Add(s.ToString() + "\n");
}

CodeRun - 動態編譯執行引擎

public class CodeRun
{
    public string CompilerVersion { get; set; } = "v3.5";

    public List Run(string code, string id, params string[] assemblies)
    {
        Consoler.Outputs[id] = new Consoler();
        var cp = new CompilerParameters
        {
            CompilerOptions = "/target:library /optimize",
            GenerateInMemory = true,
            IncludeDebugInformation = false
        };
        foreach (var asm in assemblies) cp.ReferencedAssemblies.Add(asm);
        cp.ReferencedAssemblies.AddRange(new[] { "mscorlib.dll", "System.dll", "System.Core.dll", "VSOnline.Framework.dll" });

        var provider = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", CompilerVersion } });
        code = code.Replace("Console.WriteLine", $"VSOnline.Framework.Consoler.Outputs[\"{id}\"].WriteLine");
        code = code.Replace("Console.Write", $"VSOnline.Framework.Consoler.Outputs[\"{id}\"].Write");

        var results = provider.CompileAssemblyFromSource(cp, code);
        if (results.Errors.HasErrors)
        {
            foreach (CompilerError err in results.Errors)
                Consoler.Outputs[id].Output.Add(err.ErrorText + "\n");
            return ReturnOutput(id);
        }

        var asm = results.CompiledAssembly;
        var program = asm.CreateInstance("Program");
        program.GetType().GetMethod("Main").Invoke(program, null);
        return ReturnOutput(id);
    }

    List ReturnOutput(string id)
    {
        var arr = new string[Consoler.Outputs[id].Output.Count];
        Consoler.Outputs[id].Output.CopyTo(arr, 0);
        Consoler.Outputs.Remove(id);
        return new List(arr);
    }
}

關鍵技巧

  • 字串取代將 Console 導向 Consoler,避免重導向標準輸出流的複雜性。
  • CompilerParameters.GenerateInMemory = true 直接在記憶體產生組件,無臨時檔案。
  • 每次執行使用唯一 id 隔離輸出緩衝區。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved