我正在编写一个控制台工具来为类库中的对象生成一些C#代码。我可以实际生成代码的最好/最简单的方法是在构建库之后使用反射。它运作得很好,但这似乎是一个随意的approch充其量。由于生成的代码将使用库进行编译,因此在进行更改后,我需要构建解决方案两次以获得最终结果等。其中一些问题可以通过构建脚本来缓解,但它仍然感觉像是对我来说太过分了。
我的问题是,对于这类事情,是否有任何高级别的最佳做法?
答案 0 :(得分:2)
目前还不清楚你在做什么,但看起来很清楚你有一些基线代码,并且基于它的一些属性,你想要生成更多的代码。
所以这里的关键问题是,根据基线代码,你如何提取有趣的属性,以及如何从这些属性生成代码?
反射是一种将运行(好,至少加载)的代码属性提取到与反射用户代码相同的执行环境中的方法。反射的问题是它只提供了一组非常有限的属性,通常是类,方法或参数名称的列表。如果您想要做的所有代码生成都可以完成,那么反射似乎很好。但是如果你想要更详细的代码属性,反射就不会削减它。
实际上,唯一能从中提取真正任意代码属性的工件是源代码作为字符串(你怎么回答,是add运算符和变量中间的T之间的字符数) name是素数?)。实际上,从字符串中获取的属性通常不是很有用(参见我刚给出的示例:)。
编译人员在过去的60年里一直在研究如何提取有趣的程序属性,而你却完全不能理会他们在半个世纪中所学到的东西。
他们已经确定了许多相对标准的“编译器数据结构”:抽象语法树(AST),符号表(ST),控制流图(CFG),数据流事实(DFF),程序三元组,思考分析等 如果您想分析或生成代码,最好的办法是先将它处理成这样的标准编译器数据结构,然后再完成工作。如果您有AST,您可以回答有关使用哪些运算符和操作数的各种问题。如果您有ST,您可以回答有关where-defined,where-visible和what-type的问题。如果你有CFG,你可以回答有关“之前的事情”,“陈述X依赖的条件”的问题。如果您有DFF,则可以确定哪些分配会影响代码中某个点的操作。反射将永远不会提供这个恕我直言,因为它将始终限于运行时系统开发人员在运行程序时愿意保留的内容。 (也许有一天他们会保留所有的编译器数据结构,但它不会是反射;它最终将成为编译器支持)。
现在,在确定了感兴趣的属性后,您如何处理代码?在这里,编译人员如此专注于生成机器代码,他们不提供标准答案。这些人是程序转换社区(http://en.wikipedia.org/wiki/Program_transformation)。这里的想法是将程序的至少一个表示保存为AST,并为匹配源代码语法提供特殊支持(通过从感兴趣的代码片段构造模式匹配AST),并提供“重写”规则。效果,“当你看到这种模式,然后在这种情况下用该模式替换它”。 通过将条件连接到编译器人员的各种属性提取机制,您可以相对简单地说出您希望通过50年的经验支持的内容。这样的程序转换系统具有读取源代码的能力, 进行分析和转换,通常在转换后重新生成代码。
对于您的代码生成任务,您将基线代码读入AST,应用分析来确定有趣的属性,使用转换生成新的AST,然后吐出答案。
为了使这样的系统有用,它还必须能够解析和绘制各种源代码语言,以便C#爱好者以外的人也可以享受代码分析和生成的好处。
这些想法都在于 DMS Software Reengineering Toolkit。 DMS处理C,C ++,C#,Java,COBOL,JavaScript,PHP,Verilog,以及许多其他语言。
(我是DMS的架构师,所以我有一个相当偏见的观点.YMMV)。
答案 1 :(得分:1)
您可能希望使用CodeDom,这样您只需构建一次。
首先,我会阅读this CodeProject article以确保在没有使用反射的情况下,您无法支持特定于语言的功能。
答案 2 :(得分:1)
您是否考虑过使用T4模板执行代码生成?看起来它现在得到了更多的宣传和关注,并且在VS2010中获得了更多的支持。
本教程似乎以数据库为中心,但它可能会给你一些指示:http://www.olegsych.com/2008/09/t4-tutorial-creatating-your-first-code-generator/此外T4上最近有一个Hanselminutes:http://www.hanselminutes.com/default.aspx?showID=170。
编辑:另一个很棒的地方是StackOverflow上的T4标记:https://stackoverflow.com/questions/tagged/t4
编辑:(通过提问者,新发展)
从VS2012开始,T4现在只需一步即可支持对活动项目的反射。这意味着您可以对代码进行更改,T4模板的编译输出将反映最新版本,而无需执行第二个反射/构建步骤。有了这个功能,我将此标记为已接受的答案。
答案 3 :(得分:0)
据我所知,您可以使用Common Compiler Infrastructure(http://ccimetadata.codeplex.com/)之类的程序来编程分析现有的c#源代码。
这对我来说非常复杂,CCI显然只对C#语言规范2提供全面支持。更好的策略可能是简化现有方法。
答案 4 :(得分:0)
我不确定这样做的最好方法,但你可以这样做
作为另一个制作后步骤,请运行csc
或msbuild
来构建生成的dll
依赖于生成的dll的其他内容也需要依赖于基本dll,因此构建顺序保持正确