• 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();
        }

    }
  • 相关阅读:
    指针与应用的区别:《程序员面试宝典的一道题目》
    一道关于sizeof()的困惑的笔试题
    静态变量存储方式
    编译和链接的区别联系
    一些基本的数据格式小问题
    [多线程] 多线程的问题
    [多线程] 停止和暂停线程以及线程的优先级,同步锁
    [多线程] 线程中的常用方法-最详细
    [多线程] 线程的运行状态及上下文切换
    [多线程] 新建线程以及线程的运行
  • 原文地址:https://www.cnblogs.com/flaaash/p/3084877.html
Copyright © 2020-2023  润新知