C#如何从代码生成代码

7

是否有可能根据同一项目中的代码生成和构建一些C#代码?我尝试使用T4和Reflection,但存在某些程序集锁定问题。还有其他方法吗?


我可以问一下是什么让你对内省引擎不感兴趣吗?http://www.olegsych.com/2007/12/how-to-use-t4-to-generate-decorator-classes/ - Rob Fonseca-Ensor
Microsoft.Cci.dll和FxCop许可证存在一些问题。不允许单独使用它们。此外,我非常熟悉T4引擎。 - Marko
1
从VS 2010 SP1开始,使用T4进行反射时应该不会出现锁定问题 - Jon
5个回答

1

你绝对可以编写自己的代码生成器,全部使用C# - 毕竟,“生成”的“代码”只是你写出来的文本文件。

但是T4模板有什么问题吗?它们提供了许多功能,您不必再次重新发明轮子-为什么不使用它呢?您能否更详细地告诉我们您在使用T4时遇到的问题?

T4实际上只是.NET中的一堆类-因此,您绝对可以编写自己的代码生成器来处理某些逻辑,并使用T4进行模板化和替换这些模板值部分。但是:为了帮助您诊断T4问题,我们需要更多了解这些问题....


例如,我想为我的 L2S 模型生成 CloneEntity。 我需要读取属性并生成 Clone 方法。这可以通过 T4 和反射来完成,但是有关程序集锁定的问题。您必须在每次运行后关闭 VS 并重新打开它。 - Marko
1
关于CloneEntity:为什么不将实体序列化到内存流中,然后从那里反序列化呢?这是标准方法,已经证明其价值,不需要任何诡计或代码生成... - marc_s

1

反射对我来说很有效。您可以通过在VS中将构建任务隔离到单独的AppDomain中来解决程序集锁定问题。当任务完成时,您需要用于代码生成的任何程序集都将与任务的AppDomain一起卸载。请参见AppDomainIsolatedTask


我不确定是否理解正确。我需要编写自己的构建任务,该任务继承AppDomainIsolatedTask并启动T4代码生成器。是这样吗? - Marko
是的,这样你应该能够在构建过程中解决VS锁定程序集的问题。至于实际的代码生成器,使用最适合你的——如果你喜欢T4,那就用T4吧。 - Anton Tykhyy

1

这个来自Oleg Sych的例子使用了FXCop的内省引擎而不是反射。这样,程序集就不会被锁定。

不幸的是,反射是为代码执行进行优化的。其中一个限制使其不适合用于代码生成 - 使用反射加载的程序集只能随其AppDomain一起卸载。因为T4模板编译成.NET程序集并缓存以提高代码生成的性能,使用反射访问组件程序集会导致T4锁定它。

或者,如果您只针对Linq to SQL类,则可以从dbml文件中生成代码,而不是从L2S从dbml生成的代码。 我在自己的博客上有一个类似的示例(edmx文件)


0

0

这真的取决于您想要实现什么,但一般情况下,我建议使用T4模板。

是的,您可以在项目内部使用T4模板来根据某些本地设置生成代码,但您应该定义您要做什么。

如果您想要根据同一项目中定义的某些类生成代码-这似乎不是很容易实现的事情(毕竟您想编译当前项目中的一些类,基于它们生成一些代码,然后再次生成类...嗯...?)

但是,如果您想存储一些设置,然后运行T4模板并根据这些设置生成一些代码-这是非常容易实现的。T4MVC就是一个例子(他们根据复制并存储在T4模板旁边的项目中的设置文件生成代码)。该模板还查看解决方案中可用的当前文件,并基于每个文件生成字符串常量。这听起来可能确实有助于您解决问题,无论它是什么:)

如果您仍然不确定-您可以指定更多关于您想要做什么的细节,我们将尝试帮助您:)


谢谢你的回答。我想要实现的是能够根据项目中的类生成额外的代码。比如CloneEntity()、SerializeEntity()或InvokeSomeMethod等。所有这些代码都依赖于类名、成员等。生成的代码可以在另一个项目中,但最好还是把所有东西放在一起。 - Marko
我明白了。由于您正在尝试在半生成的实体上生成代码,我认为您很可能需要将这些类放在单独的项目中。听起来,如果您按照完全相同的方法进行操作,但将这些T4放在单独的程序集中,它应该可以正常工作(当然,它不必仅包含T4的单独程序集..您可以在其中放置任何其他类型的内容,但是T4应该反映已编译的单独程序集中的类 :) )祝你好运! - Artiom Chilaru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接