Net有道

紫冠道人的求道历程

导航

<2004年11月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

与我联系

搜索

 

常用链接

留言簿(21)

我参与的团队

随笔分类

随笔档案

文章分类

文章档案

Program

程序之外的生活

我的阅读BLOG

积分与排名

最新评论

阅读排行榜

评论排行榜

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

 

写着写着就已经到()了,前面讲了那么多,分析如此这般的CodeDOM代码会有什么对应的程序代码;什么样的程序代码CodeDOM程序应该是如何写。其实那都是纸上谈兵的事,一段CodeDOM程序写下来,经过一个个的Add后,最后到了CodeCompileUnit这个CodeDOM容器就停了,没地方可以Add了。就凭这个CodeCompileUnit是不会凭空产生出来我们要的那些代码的喽,CodeDOM只是一个模型而已,只是一个抽象的数据结构。下面的任务就是根据那个CodeDOM生成我们要的源代码(C#VBJScript)

生成与后面的编译源代码用到的是另外一个命名空间----System.CodeDOM.Compiler中的类,这个命名空间比System.CodeDOM那个要瘦多了,主要就是生成与编译时的一些设置,主要的功能都体现在三个接口:ICodeCompilerICodeGeneratorICodeParser。前两个是编译与生成代码用的,第三个是代码语法分析,可以根据具体的代码分析得到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:说是要不要在每个iftry块结束时追加elsecatchfinally块,默认为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这个文件里了。

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

posted on 2004-11-09 13:58 lichdr 阅读(2897) 评论(6)  编辑 收藏 网摘 所属分类: CodeDOM

评论

#1楼  2005-08-15 18:25 Flair@ZJU [未注册用户]

有没有实现ICodeParser接口写过parser?   回复  引用    

#2楼  2005-08-27 18:45 lichdr [未注册用户]

有人写过,这系列的后面文章提到过。
很复杂的东西,就相当于写一个解释器了。   回复  引用    

#3楼  2005-09-07 12:01 linuxyf [未注册用户]

请问如果ICodeParser接口没有实现,那么我如果读取一个写好的CS源文件,然后进行动态地编译??   回复  引用    

#4楼 [楼主] 2005-09-10 11:58 lichdr      

有源文件那还不好办,直接弄个PROCESS,调命令行编译之。

可以用System.CodeDom.Compiler 里的
CompilerResults CompileAssemblyFromFile(
CompilerParameters options,
string fileName
);
这个方法。原理是一样的。ICodeCompiler这个接口有很多东西的可用的。


用ICodeParser是绕个弯了,你把源代码》》CODEDOM,然后它动态编译CODEDOM的时候内部会生成临时文件来编译的。

要明确的一点是,DOM只是一个object,这个东西与具体语言是无关的(在.NET下)。编译器是无法编译一个object的,它分析编译的是我们平时用键盘堆起来的字符串。
如果没有多语言的需求,没必要用CODEDOM的代码生成部分(当然它的编译部分可以用)。   回复  引用  查看    

#5楼  2007-07-14 21:38 Jeffrey Zhao      

好文章。
ElseOnClosing的意思是如果为true则:
if
{
} else
否则就是
if
{
}
else   回复  引用  查看    

#6楼 [楼主] 2007-07-24 13:09 lichdr      

@Jeffrey Zhao
这样啊,试了一下,果是如此,以前没仔细看生成的代码。   回复  引用  查看    





标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
Google站内搜索
找找看

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》

相关文章:

相关链接: