写着写着就已经到(七)了,前面讲了那么多,分析如此这般的CodeDOM代码会有什么对应的程序代码;什么样的程序代码CodeDOM程序应该是如何写。其实那都是纸上谈兵的事,一段CodeDOM程序写下来,经过一个个的Add后,最后到了CodeCompileUnit这个CodeDOM容器就停了,没地方可以Add了。就凭这个CodeCompileUnit是不会凭空产生出来我们要的那些代码的喽,CodeDOM只是一个模型而已,只是一个抽象的数据结构。下面的任务就是根据那个CodeDOM生成我们要的源代码(C#、VB或JScript)。
生成与后面的编译源代码用到的是另外一个命名空间----System.CodeDOM.Compiler中的类,这个命名空间比System.CodeDOM那个要瘦多了,主要就是生成与编译时的一些设置,主要的功能都体现在三个接口:ICodeCompiler、ICodeGenerator、ICodeParser。前两个是编译与生成代码用的,第三个是代码语法分析,可以根据具体的代码分析得到CodeDOM,不过目前这个接口是空的,还没有一个类来实现它。
看一下ICodeGenerator这个接口的方法,发现它主要是几个GeneratorCodeFrom*之类的方法,从这可以发现要生成源代码不一定要从CodeCompileUnit来生成。如可以直接从Expression生成代码(GeneratorCodeFromExpression)、可以直接单独生成一个类的代码(GeneratorCodeFromType)等等,它们的用法是大同小异。我们为了得到完整的代码文件就只用GeneratorCodeFromCompileUnit来说事了。
先要得到ICodGenerator这个接口,这个接口要从CodeDomProvider得到(在System.CodeDOM.Compiler中的三个接口都要从CodeDomProvider这里来得到接口),具体如下:
CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeGenerator gen = provider.CreateGenerator();
(CSharpCodeProvider是从抽象类CodeDomProvider继承下来的具体类,这里根据要产生的不同源代码选择不同的Provider。如VB就用VBCodeProvider。)
好,得到接口,就可以GeneratorCodeFromCompileUnit了。这个方法的参数
void GenerateCodeFromCompileUnit(
CodeCompileUnit e,
TextWriter w,
CodeGeneratorOptions o
);
第一个参数就是来源了(其他几个From*的方法就是这里跟*FromCompileUnit有点区别而已),第二个参数就是目的地(要输出的代码写到哪去呢?写到这个TextWriter里),一切麻烦的东西都在第三个参数上,不过这个Option倒是比较的简单的,设置的东西也比较的少。
CodeGeneratorOptions里的东西都是一些细枝未节的东西了,一般用默认值就行了。
BlankLinesBetweenMembers:成员之间是否插入空行,默认是true。一般不要动它了,在类成员之间加个空行看起来也舒服点;
BracingStyle:大括号的样式,默认情况下为Block(字符串),左大括号不另起一行;左大括号如果要另起一行就设为C。我一般喜欢把左大括号与它的关联语句放在同一行,这个也不用另设。
ElseOnClosing:说是要不要在每个if或try块结束时追加else、catch或finally块,默认为false。不过我设了一下true,好象不起作用。不知哪里错了。
IndentString:缩进用的字符串。默认为四个空格。这个也不用改了,这样看起来挺舒服的。
所以下面一点代码就是:
StreamWriter sw = new StreamWriter(Filename,false);
CodeGeneratorOptions geneop = new CodeGeneratorOptions();
//geneop.BlankLinesBetweenMembers = false;
//geneop.BracingStyle = "C";
//geneop.ElseOnClosing = true;
//geneop.IndentString = " ";
gen.GenerateCodeFromCompileUnit(CodeComU,sw,geneop);
sw.Close();
这之后根据CodeComU这个CodeDOM产生的代码就在Filename这个文件里了。
生成代码真是简单,五、六句就搞定了。