继上节我们把Code 表达式编译成为了Code代码,有时我们只想动态编译程序集,在内存中或者是
硬盘上调用,这就是CodeDom的动态编译。微软在CodeDom中提供了动态编译程序,这是ICodeComp
iler的用武之地了,它定义用于调用源代码编译的接口或使用指定编译器的 CodeDOM 树。可以从CodeDomProvider生成引用对象:CodeDomProvider.CreateProvider("").CreateCompiler();
在ICodeCompiler中为我们提供了程序集编译的方法有:
CompileAssemblyFromDom :使用指定的编译器设置从指定的 CodeCompileUnit 所包含的 System.CodeDom 树中编译程序集。
CompileAssemblyFromDomBatch:基于包含在 CodeCompileUnit 对象的指定数组中的 System.CodeDom 树,使用指定的编译器设置编译程序集。
CompileAssemblyFromFile:从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。
CompileAssemblyFromFileBatch:从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。
CompileAssemblyFromSource: 从包含源代码的指定字符串,使用指定的编译器设置编译程序集。
CompileAssemblyFromSourceBatch:从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。在我们的CodeDomProvider也提供了CompileAssemblyFromDom、CompileAssemblyFromFile、CompileAssemblyFromSource。
在他们的编译时候都有一个变异参数CompilerParameters,提供了编译时参数选项:
CompilerOptions:获取或设置调用编译器时使用的可选附加命令行参数字符串。
EmbeddedResources:获取要在编译程序集输出时包含的 .NET Framework 资源文件。
Evidence:指定一个证据对象,该对象表示要授予已编译的程序集的安全策略权限。
GenerateExecutable:获取或设置一个值,该值指示是否生成可执行文件。
GenerateInMemory:获取或设置一个值,该值指示是否在内存中生成输出。
IncludeDebugInformation:获取或设置一个值,该值指示是否在已编译的可执行文件中包含调试信息。
LinkedResources:获取当前源中引用的 .NET Framework 资源文件。
MainClass:获取或设置主类的名称。
OutputAssembly:获取或设置输出程序集的名称。
ReferencedAssemblies:获取当前项目所引用的程序集。
TempFiles:获取或设置包含临时文件的集合.
TreatWarningsAsErrors:获取或设置一个值,该值指示是否将警告视为错误。
UserToken:获取或设置在创建编译器进程时使用的用户标记。
WarningLevel:获取或设置使编译器中止编译的警告级别。
Win32Resource:获取或设置要链接到已编译程序集中的 Win32 资源文件的文件名。他们的结果返回编译结果CompilerResults,提供了编译结果信息:
CompiledAssembly:获取或设置已编译的程序集。
Errors:获取编译器错误和警告的集合。
Evidence:指示证据对象,该对象表示编译的程序集的安全策略权限。
NativeCompilerReturnValue:获取或设置编译器的返回值。
Output:获取编译器输出消息。
PathToAssembly:获取或设置已编译程序集的路径。
TempFiles:获取或设置要使用的临时文件集合。下面我们就来的Demo:实现简单的HelloWord编译:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.CodeDom; using System.CodeDom.Compiler; namespace CodeDomDemo4 { class Program { static void Main(string[] args) { Program pro = new Program(); CodeCompileUnit unit= pro.CodeDomHelloDemo(); Console.WriteLine(pro.GenerateCode(unit, "c#")); Console.WriteLine(pro.GenerateCode(unit, "vb")); CompilerResults result= pro.CompilerCode(unit, "c#"); if (result.Errors != null) { foreach (var item in result.Errors) { Console.WriteLine(item); } } Console.Read(); } public string GenerateCode(CodeCompileUnit unit, string language) { StringBuilder sb = new StringBuilder(); System.IO.StringWriter sw = new System.IO.StringWriter(); CodeDomProvider.CreateProvider(language).GenerateCodeFromCompileUnit(unit, sw,null); sw.Close(); return sw.ToString(); } public CompilerResults CompilerCode(CodeCompileUnit unit, string language) { CompilerParameters option = new CompilerParameters(); option.GenerateExecutable = true; option.GenerateInMemory = false; option.IncludeDebugInformation = true; option.ReferencedAssemblies.Add("System.dll"); option.OutputAssembly = "Demo5.exe"; return CodeDomProvider.CreateProvider(language).CompileAssemblyFromDom(option,unit); } public CodeCompileUnit CodeDomHelloDemo() { //Mehtod CodeEntryPointMethod method = new CodeEntryPointMethod(); //Console.WriteLine("Hello Word!"); CodeMethodInvokeExpression methodWrite = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(typeof(Console)), "WriteLine",new CodePrimitiveExpression("Hello Word!")); //Console.Read(); CodeMethodInvokeExpression methodread = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(typeof(Console)), "Read"); method.Statements.Add(methodWrite); method.Statements.Add( methodread); //class Hello CodeTypeDeclaration hello = new CodeTypeDeclaration("Hello"); hello.Attributes = MemberAttributes.Public; hello.Members.Add(method); //namespace Demo5 CodeNamespace nspace = new CodeNamespace("Demo5"); nspace.Imports.Add(new CodeNamespaceImport("System")); nspace.Types.Add(hello); //CodeCompileUnit CodeCompileUnit unit = new CodeCompileUnit(); unit.Namespaces.Add(nspace); return unit; } } }输出代码为:
//------------------------------------------------------------------------------ // <auto-generated> // 此代码由工具生成。 // 运行时版本:2.0.50727.4927 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // </auto-generated> //------------------------------------------------------------------------------ namespace Demo5 { using System; public class Hello { public static void Main() { System.Console.WriteLine("Hello Word!"); System.Console.Read(); } } } '------------------------------------------------------------------------------ ' <auto-generated> ' 此代码由工具生成。 ' 运行时版本:2.0.50727.4927 ' ' 对此文件的更改可能会导致不正确的行为,并且如果 ' 重新生成代码,这些更改将会丢失。 ' </auto-generated> '------------------------------------------------------------------------------ Option Strict Off Option Explicit On Imports System Namespace Demo5 Public Class Hello Public Shared Sub Main() System.Console.WriteLine("Hello Word!") System.Console.Read End Sub End Class End Namespace 在bin/debug下有生成Demo5.exe和Demo5.pdb文件:点击Demo5.exe运行视图:今天就写到这里,睡觉了。CodeDom很简单,要了解的东西并不多。下面如果有机会就写几个示例Demo,
暂时考虑自动生成一些算法Code, 没有实际意义,或者是做个类编译器。 欢迎大家指正,共同学习共同进步。