C#即时编译器技术测试

用visual studio编写测试程序需要新建solution,然后project,命名和存盘都是麻烦事。可以考虑写一个自己的编译环境。
通过  Microsoft.CSharp.CSharpCodeProvider() 对象的 CompileAssemblyFromSource(parameters,codes) 方法就能得到编译结果对象 CompilerResults;然后结果对象再通过反射机制  result.CompiledAssembly.GetType("Phoenix") 就可以通过编译生成的程序集包含Main方法的类型。然后你可以 Phoenix.GetMethod("Main").Invoke(null,new string[]{});呼叫输出结果。

原理上说无非是构造csc可编译的完整源代码,然后生成assembly,当然是以临时文件形式存盘的,然后用reflect解析执行Main方法输出结果,如果用WinForm,可以用Console.SetOut重定向输出结果到控件。

测试代码如下,程序会编译文本 Console.WriteLine(\"Phoenix, from ashes it was born!\");:并给出结果!

using System;
using System.CodeDom.Compiler;


public class MyClass
{
    private static string GenerateCode(string userCode)
    {
        string namespaces =@"using System;using System.ComponentModel;using System.Text;using System.Text.RegularExpressions;using System.IO;using System.Collections;using System.Collections.Generic;using System.Windows.Forms;using System.Threading;using System.Reflection;";
        string codeHead = @"
            sealed class Phoenix
            {
                public static void Main()
                {
";
                    //userCode here
        string codeTail = @"
                }
            }
";        
        string compileCodes = namespaces + codeHead + userCode + codeTail;
        return compileCodes;
    }
    
    private static CompilerResults Compile(string codes)
    {
        //CSharpCodeProvider
        System.CodeDom.Compiler.CodeDomProvider compiler = new Microsoft.CSharp.CSharpCodeProvider();
        //CompilerParameters
        System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
        parameters.WarningLevel = 4;
        parameters.GenerateExecutable = false;
        parameters.GenerateInMemory = true;
        parameters.ReferencedAssemblies.Add("System.dll");
        parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");    
        //Compile: if successfully, we get the assembly with a temp filename    
        return compiler.CompileAssemblyFromSource(parameters,codes);
    }
    
    public static void Main()
    {
        string userCode = "Console.WriteLine(\"Phoenix, from ashes it was born!\");";
        string compileCodes = GenerateCode(userCode);
        //Compile the codes and get the CompilerResults OBJECT
        System.CodeDom.Compiler.CompilerResults result = Compile(compileCodes);
        
        if(result.Errors.HasErrors)
        {
            //here, we output the error to output OBJECT
            foreach (CompilerError error in result.Errors) {
                Console.WriteLine(error.Line + ":" + error.ErrorText);
            }
            Console.ReadKey();
            return;
        }
        //output the result
        Console.WriteLine(result.CompiledAssembly.FullName);
        
        Type Phoenix = result.CompiledAssembly.GetType("Phoenix");
        try
        {
            Phoenix.GetMethod("Main").Invoke(null,new string[]{});
        }
        catch(System.Reflection.TargetInvocationException ex)
        {
            Console.WriteLine(ex);
        }
        Console.ReadKey();
    }

}
原文地址:https://www.cnblogs.com/flaaash/p/3084877.html