动态生成与编译(七)----根据CodeDOM生成源代码

来源:百度文库 编辑:神马文学网 时间:2024/04/29 16:00:30

动态生成与编译(七)----根据CodeDOM生成源代码

 

写着写着就已经到(七)了,前面讲了那么多,分析如此这般的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这个文件里了。

生成代码真是简单,五、六句就搞定了。