在微软的自家代码生成方案中我们有两种选择方式:CodeDom 和Text Template Transformation Toolkit(T4)模板。同样我们可以利用简单的String或者StringBuilder来拼接字符串,但是那对于简单的还可以,但是对于复杂的问题就悲伤。其实在ASP.NET MVC 3.0中有多处了一个更简洁语法的模板-Razor,我们同样可以运用于我们自己的代码生成中,我随便有一篇简单的介绍Razor Templating Engine,在以后有机会了会写Razor Demo。今天的主题不在这里,所以不多说了。

一:简介:

CodeDom:这 个类库出现在我们的.NET Framework 2.0,并且被深深的用于我们的ASP.NET项目中。CodeDom关注于一个语言独立性,以至于我们可以利用我们熟悉的语言(c#,vb等)构建一个CodeDom Model Tree,就可以生成我们在.NET平台所支持的语言代码。对于我们的ASP.NET要求语言的独立。

T4:T4模板作为VS2008的一部分出现,他以<# #> 、<#= #>接近于ASP.NET的语言在模板中插入一段段的动态代码块,可以像asp或者ASP.NET一样简单的更让人贴切,相对于CodeDom就更简洁,但是没有了语言层次的抽象,不具有语言独立性,我们必须为同一个功能的模板在不同的语言上写不同的模板,但是在开发中往往c#模板就足够了,以及更简单化所以得到了更多人的青睐。

二:Code Demo:

下面我们将用CodeDom和t4分别生成一个简单的Code,根据时间输出不同的问候,如下:

1:CodeDom Code:

  1. 代码   
  2.  
  3. using System;   
  4. using System.Text;   
  5. using System.CodeDom;   
  6. using System.IO;  
  7.  
  8. namespace RazorDemo   
  9. {   
  10.     public class CodedomDemo   
  11.     {   
  12.         public CodeCompileUnit CrateCodeCompileUnit()   
  13.         {   
  14.             var testClass = new CodeTypeDeclaration("Test");   
  15.             var testMeth = new CodeMemberMethod()   
  16.             {   
  17.                 Attributes = MemberAttributes.Public| MemberAttributes.Final,   
  18.                 Name = "SayHello",   
  19.             };   
  20.             var param = new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "name");   
  21.             testMeth.Parameters.Add(param);   
  22.             testClass.Members.Add(testMeth);  
  23.  
  24.             var nowExpression = new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(DateTime)), "Now"), "Hour");   
  25.             var assmon = new CodeBinaryOperatorExpression(new CodePrimitiveExpression("早上好:"), CodeBinaryOperatorType.Add, new CodeArgumentReferenceExpression("name") );   
  26.             var asslunch = new CodeBinaryOperatorExpression(new CodePrimitiveExpression("中午好:"), CodeBinaryOperatorType.Add, new CodeArgumentReferenceExpression("name"));   
  27.             var assAfternoon = new CodeBinaryOperatorExpression(new CodePrimitiveExpression("下午好:"), CodeBinaryOperatorType.Add, new CodeArgumentReferenceExpression("name"));   
  28.             var codecondition = new CodeConditionStatement(new CodeBinaryOperatorExpression(   
  29.                 nowExpression, CodeBinaryOperatorType.LessThanOrEqual, new CodePrimitiveExpression(10)),   
  30.                 new CodeStatement[] { new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(Console)), "WriteLine", assmon)) },           //true:if(DateTime.Now<=10)   
  31.                 //else   
  32.                 new CodeStatement[]   
  33.                 {   
  34.                    new CodeConditionStatement(new CodeBinaryOperatorExpression(nowExpression, CodeBinaryOperatorType.LessThanOrEqual,new CodePrimitiveExpression(14) ),  // else if(DateTime.Now<=14)   
  35.                      new CodeStatement[] { new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(Console)), "WriteLine",asslunch))},    //true   
  36.                      new CodeStatement[] { new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(Console)), "WriteLine",assAfternoon))}) //fasle   
  37.                 }   
  38.                );  
  39.  
  40.             testMeth.Statements.AddRange(new CodeStatement[] {               
  41.             codecondition   
  42.             });  
  43.  
  44.             var ns = new CodeNamespace("Wolf");   
  45.             ns.Imports.Add(new CodeNamespaceImport("System"));   
  46.             ns.Types.Add(testClass);   
  47.             var util = new CodeCompileUnit();   
  48.             util.Namespaces.Add(ns);   
  49.             return util;   
  50.         }  
  51.  
  52.         public string Genertor(string language)   
  53.         {   
  54.             StringBuilder sb = new StringBuilder();   
  55.             StringWriter sw = new StringWriter(sb);   
  56.             System.CodeDom.Compiler.CodeDomProvider.CreateProvider(language).GenerateCodeFromCompileUnit(   
  57.                 this.CrateCodeCompileUnit(), sw, new System.CodeDom.Compiler.CodeGeneratorOptions()   
  58.                 {   
  59.                     ElseOnClosing = true,   
  60.                     IndentString = "    "   
  61.                 });   
  62.             sw.Close();   
  63.             return sb.ToString();  
  64.  
  65.         }   
  66.     }   
  67. }   
  68.  
  69.  
  70. 复制代码 

2:T4 Code:

  1. 代码   
  2.  
  3. <#@ template language="C#" #>  
  4.  
  5. using System;   
  6. namespace WolfT4 {     
  7.     public class Test {  
  8.  
  9.         public void SayHello(string name) {   
  10.             <# if(System.DateTime.Now.Hour<=10){#>   
  11.             System.Console.WriteLine(("早上好:" + name));   
  12.             <#} else if(System.DateTime.Now.Hour<=14){#>   
  13.             System.Console.WriteLine(("中午好:" + name));   
  14.             <#} else{ #>   
  15.             System.Console.WriteLine(("下午好:" + name));   
  16.             <#}#>              
  17.         }   
  18.     }   
  19. }  
  20.  
  21.  
  22. 复制代码 

三:总结:

CodeDom的优势:

1:具有语言层次抽象,独立性:是一个单语言开发,多语言生成的方式。

2:Framework 的支持:作为我们的.NET Framework 一部分出现的,位于System.CodeDom命名空间下。不需要想T4 模板一样引用Microsoft.VisualStudio.TextTemplating.dll

T4优势:

1:更加贴切:采用的是类似于ASP、ASP.NET的语言块,是的我们的开发更贴切,采用模板方式更加简洁,快速。

2:可维护性:由于是基于文件,不像codedom编译成为dll方式,我们可以随时修改Template文件、重构。

其实我觉得只要是不要求语言独立性,多语言生成的话,就采用T4或者Razor等模板。

代码生成技术(目前完成,还在继续,好久没写了...):

1:CodeDom系列目录

2:CodeSmith模板引擎系列-目录

3:Razor Templating Engine