最近手头项目接触到了CodeDom,顺带着在这里做个系列文章,有兴趣的可以做个参考。
CodeDOM是个用于运行时生成代码,以及编译生成的代码的相关技术。我们通过构造CodeDOM这样的DOM树 来自动生成代码。
和反射都属于动态编程相关的技术。我们知道反射用的比较多的地方在于各种框架,在运行时创建实例以及相关操作。那CodeDOM有哪些用途呢?
MSDN---
CodeDOM 的一些一般用途包括:
-
模板化代码生成:生成 ASP.NET、XML Web 服务客户端代理、代码向导、设计器或其他代码发出机制的代码。
-
动态编译:支持以一种或多种语言进行代码编译。动态编译我们怕是没什么机会接触了,那就剩下第一种可能。第一种用途也说的很含糊,我们暂且不管,code起来再说。我们以一个简单的例子做解释
class Program { //codedom 这种东西 是用来自动生成代码的,而生成什么样的代码就依靠我们提供的codeDom代码树,这个名词很类似于html Dom,也就是 //我们编好 codedom结构树,他会帮我们什么代码。(好像理所当然的感觉) 至于生成什么样的语言的代码,则要看所提供的不同的provider. static void Main(string[] args) { GenerateCode(); //先生成,这时候 文件已经生成了 CompilerResults results = CompileCode("generatedHelloWorld.cs"); //在编译我们生成的cs文件 Console.ReadKey(); } //构造dom树 创建编译单元.这一步是我们写代码的主体 public static CodeCompileUnit createCompileUnit() { CodeCompileUnit compileUnit = new CodeCompileUnit(); //开始构造最简单的代码树, 先把各个节点创建出来 再关联他们之间的关系。 //命名空间 CodeNamespace ns = new CodeNamespace("Demo"); //类名 CodeTypeDeclaration typename = new CodeTypeDeclaration("Test"); //定义一个main入口方法 CodeEntryPointMethod entry = new CodeEntryPointMethod(); //在main方法里面输出console.writeline(helloworld); CodeMethodInvokeExpression expression_1 = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("System.Console"), "WriteLine", new CodePrimitiveExpression("Hello world! This is auto generated code ,Congratulations!") ); //再输出一句console.readkey(); CodeMethodInvokeExpression expression_2 = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("System.Console"), "ReadKey" ); //连接节点 compileUnit.Namespaces.Add(ns); ns.Imports.Add(new CodeNamespaceImport("System")); ns.Types.Add(typename); typename.Members.Add(entry); entry.Statements.Add(expression_1); entry.Statements.Add(expression_2); return compileUnit; } //重要的对象就是 generator compiler 以及parser //根据创建的编译单元 生成代码 public static void GenerateCode() { //用于生成C#代码的provider CSharpCodeProvider provider = new CSharpCodeProvider(); ICodeGenerator generator = provider.CreateGenerator(); StreamWriter writer = new StreamWriter("generatedHelloWorld.cs",false); generator.GenerateCodeFromCompileUnit(createCompileUnit(),writer,new CodeGeneratorOptions()); writer.Close(); } //编译自动生成的源码 public static CompilerResults CompileCode(string filepath) { CSharpCodeProvider provider = new CSharpCodeProvider(); ICodeCompiler compiler = provider.CreateCompiler(); //我们还需要提供一些编译所需要的参数 CompilerParameters paras = new CompilerParameters(new string[]{"System.dll"},"HelloWorld.exe",false); paras.GenerateExecutable = true; CompilerResults results = compiler.CompileAssemblyFromFile(paras,filepath); return results; } }
步骤其实并不复杂,就是 拼接compileUnit树, 根据树生成.cs文件,编译生成的文件。在运行我们上面的程序之后 发现,文件夹多了一些东西
就是我们生成的文件,运行HelloWorld.exe
很开森有木有!看来和CodeDom初识还是愉悦的~