c#动态编译,动态生成程序集

本文介绍如何使用C#进行动态编译,包括使用CSharpCodeProvider类及其方法,如CompileAssemblyFromDom和CompileAssemblyFromSource等。同时展示了两种编译方式的例子:文件编译和内存编译。

首先引入命名空间

using System.CodeDom.Compiler;


 

其次我们要了解CSharpCodeProvider这个类是用于动态编译c#程序集,它继承了ICodeCompiler

 在使用动态编译前,应该先了解反射的相关知识

 

在动态编译时,提供了多种方式如下:

CompileAssemblyFromDom
使用指定的编译器设置从指定的 CodeCompileUnit 所包含的 System.CodeDom 树中编译程序集。
CompileAssemblyFromDomBatch
基于包含在 CodeCompileUnit 对象的指定数组中的 System.CodeDom 树,使用指定的编译器设置编译程序集。
CompileAssemblyFromFile
从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。
CompileAssemblyFromFileBatch
从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。
CompileAssemblyFromSource
从包含源代码的指定字符串,使用指定的编译器设置编译程序集。
CompileAssemblyFromSourceBatch
从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。

 

在编译时,我们可以选择是exe或dll。当然,我们也可以只在内存编译,不用生成文件,程序集用完就可以释放。

下面是一个实例

using System;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.CodeDom;

namespace PG
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建编译器对象
            CSharpCodeProvider p = new CSharpCodeProvider();
            ICodeCompiler cc = p.CreateCompiler();

            // 设置编译参数
            CompilerParameters options = new CompilerParameters();
            options.ReferencedAssemblies.Add("System.dll");
            options.GenerateExecutable = true;
            options.OutputAssembly = "HelloWorld.exe";

            //options.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            //options.EmbeddedResources.Add("Data.xml"); // 添加内置资源
            //options.CompilerOptions += " /target:winexe";
            //options.CompilerOptions += " /res:Resource1.res";
            //options.CompilerOptions += " /win32icon:test.ico";

            // 创建源码

            // 1. 使用CodeDom创建源码
            //CodeCompileUnit cu = new CodeCompileUnit();
            //CodeNamespace Samples = new CodeNamespace("Samples");
            //cu.Namespaces.Add(Samples); 
            //Samples.Imports.Add(new CodeNamespaceImport("System"));             
            //CodeTypeDeclaration Class1 = new CodeTypeDeclaration("Class1"); 
            //Samples.Types.Add(Class1); 
            //CodeEntryPointMethod Start = new CodeEntryPointMethod(); 
            //CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(  
            //    new CodeTypeReferenceExpression("System.Console"), "WriteLine", 
            //    new CodePrimitiveExpression("Hello World!") );
            //Start.Statements.Add(new CodeExpressionStatement(cs1));
            //Class1.Members.Add(Start); 

            // 2. 直接指定源码字符串
            string code = @"
                using System;
                namespace Samples
                {
                    public class Class1
                    {
                        static void Main(string[] args)
                        {
                            Console.WriteLine(""Hello, World!"");
                            Console.WriteLine(DateTime.Now.ToString());
                        }
                    }
                }
            ";
            CodeSnippetCompileUnit cu = new CodeSnippetCompileUnit(code);

            // 开始编译
            CompilerResults cr = cc.CompileAssemblyFromDom(options, cu);

            // 显示编译信息
            if (cr.Errors.Count == 0)
                Console.WriteLine("/"{0}/" compiled ok!", cr.CompiledAssembly.Location);
            else
            {
                Console.WriteLine("Complie Error:");
                foreach (CompilerError error in cr.Errors)
                    Console.WriteLine("  {0}", error);
            }

            Console.WriteLine("Press Enter key to exit...");
            Console.ReadLine();
        }

    }
}


 

下面我们来换成内存编译,用CompileAssemblyFromSource来编译

using System;
using System.Reflection;
using System.Globalization;
using Microsoft.CSharp;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Text;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            // 1.CSharpCodePrivoder 
            CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();

            // 2.ICodeComplier 
            ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();

            // 3.CompilerParameters 
            CompilerParameters objCompilerParameters = new CompilerParameters();
            objCompilerParameters.ReferencedAssemblies.Add("System.dll");
            objCompilerParameters.GenerateExecutable = false;
            objCompilerParameters.GenerateInMemory = true;

            // 4.CompilerResults 
            CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode());

            if (cr.Errors.HasErrors)
            {
                Console.WriteLine("编译错误:");
                foreach (CompilerError err in cr.Errors)
                {
                    Console.WriteLine(err.ErrorText);
                }
            }
            else
            {
                // 通过反射,调用HelloWorld的实例 
                Assembly objAssembly = cr.CompiledAssembly;
                object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
                MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");

                Console.WriteLine(objMI.Invoke(objHelloWorld, null));
            }

            Console.ReadLine();
        }

        static string GenerateCode()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("using System;");
            sb.Append(Environment.NewLine);
            sb.Append("namespace DynamicCodeGenerate");
            sb.Append(Environment.NewLine);
            sb.Append("{");
            sb.Append(Environment.NewLine);
            sb.Append("    public class HelloWorld");
            sb.Append(Environment.NewLine);
            sb.Append("    {");
            sb.Append(Environment.NewLine);
            sb.Append("        public string OutPut()");
            sb.Append(Environment.NewLine);
            sb.Append("        {");
            sb.Append(Environment.NewLine);
            sb.Append("             return /"Hello world!/";");
            sb.Append(Environment.NewLine);
            sb.Append("        }");
            sb.Append(Environment.NewLine);
            sb.Append("    }");
            sb.Append(Environment.NewLine);
            sb.Append("}");

            string code = sb.ToString();
            Console.WriteLine(code);
            Console.WriteLine();

            return code;
        }
    }
}


 

 

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值