jwe*_*ndl 9 c# generics t4 code-generation
我听说人们说不应该使用代码生成器和T4模板.这背后的逻辑是,如果您使用生成器生成代码,那么通过泛型和模板构建代码有一种更好的更有效的方法.
虽然我略微同意上面的这个陈述,但我还没有真正找到有效的方法来构建模板,例如可以说实例化自己.换句话说,我永远做不到:
return new T();
Run Code Online (Sandbox Code Playgroud)
此外,如果我想基于数据库值生成代码,我发现Microsoft.SqlServer.Management.SMO与T4模板结合使用可以很好地生成大量代码,而无需复制/粘贴或使用resharper.
我在Generics中发现的许多问题都是令我震惊的是,有很多开发人员不了解它们.当我为一个解决方案检查泛型时,有时它会变得复杂,因为C#表明你不能做一些看似合乎逻辑的事情.
你的想法是什么?你喜欢建造发电机,还是喜欢使用仿制药?此外,仿制药可以走多远?我对泛型有很多了解,但是我总是遇到陷阱和陷阱导致我使用T4模板.
处理需要大量灵活性的场景的更合适的方法是什么?哦,作为这个问题的奖励,C#和Generics的优秀资源是什么?
Pet*_*ris 15
你可以做新的T(); 如果你这样做
public class Meh<T>
where T : new()
{
public static T CreateOne()
{
return new T();
}
}
Run Code Online (Sandbox Code Playgroud)
至于代码生成器.我每天都使用一个没有任何问题.我现在正在使用一个:-)
泛型解决了一个问题,代码生成器解决了另一个问题.例如,使用UML编辑器创建业务模型,然后使用此工具生成具有持久性代码的类无法使用泛型实现,因为每个持久化类都是完全不同的.
至于仿制药的良好来源.最好的当然是Jon Skeet的书!:-)
Gar*_*thJ 14
作为T4的创始人,我不得不多次捍卫这个问题,你可以想象:-)
我的信念是,最好的代码生成是使用可重用库生成等价值的一步.
正如许多其他人所说,维护DRY的关键概念永远不会手动更改生成的代码,而是保留在源元数据更改或您在代码生成器中发现错误时重新生成的能力.此时生成的代码具有对象代码的许多特征,并且您不会遇到复制/粘贴类型问题.
一般来说,生成参数化代码生成器(特别是基于模板的系统)要比正确设计高质量的基础库(将使用成本降低到同一水平)要少得多,因此这是一种快速获取的方法.来自一致性的价值并消除重复错误.
但是,我仍然相信完成的系统通常会通过减少总代码来改进.如果不出意外,它的内存占用几乎总是会小得多(虽然人们倾向于认为泛型在这方面是免费的,但他们肯定不是这样).
如果您已经使用代码生成器实现了某些价值,那么这通常会花费您一些时间或金钱或善意来投资从生成的代码库中获取库.然后,您可以逐步重新设计代码生成器以定位新库,并希望生成更少的代码.冲洗并重复.
我所提出的一个有趣的对立点是,在这个主题中出现的是丰富,复杂的参数库在学习曲线方面并不是最简单的,特别是对于那些没有深入沉浸在平台中的人.坚持将代码生成到更简单的基本框架上可以产生冗长的代码,但它通常非常简单易读.
当然,如果您的生成器中存在大量差异和极其丰富的参数化,那么您可能只是为了模板的复杂性而牺牲产品的复杂性.这是一条很容易滑入的路径,可以让维护变得非常令人头疼 - 请注意这一点.
在我看来,代码生成器很好,只要代码生成是正常构建过程的一部分,而不是你运行一次然后保持其输出.我添加了这个警告,因为如果只使用代码生成器一次并丢弃创建它的数据,那么您只是自动创建一个大规模的DRY违规和维护问题; 而每次生成代码实际上意味着无论你用什么做生成都是真正的源代码,生成的文件只是你应该忽略的中间编译阶段.
Lex和yacc是允许您以有效方式指定功能并从中生成有效代码的工具的经典示例.尝试手工完成工作会延长开发时间,并可能产生效率较低且可读性较低的代码.虽然你当然可以将lex和yacc之类的东西直接合并到你的代码中并在运行时而不是在编译时完成它们的工作,但这肯定会给代码增加相当大的复杂性并减慢它的速度.如果你真的需要在运行时更改你的规范,那么它可能是值得的,但是在大多数正常情况下使用lex/yacc在编译时为你生成代码是一个很大的胜利.
小智 6
如果没有代码生成,Visual Studio 2010中的很大一部分将无法实现.实体框架是不可能的.将控件拖放到表单上的简单操作是不可能的,Linq也不可能.要说不应该使用代码生成是很奇怪的,因为许多人甚至没有考虑它就使用它.