目前我正在使用的项目没有完全固定的模型(由于外部影响),因此我希望能够灵活地编写它们。目前,它们被复制到应用程序的三个不同层(db,web api和客户端),每个层都有类似的逻辑(即验证)。
我想知道是否有一种方法可以让我编写一个模型文件(例如在ruby中),然后让它将该模型转换为必要的c#文件。目前看起来我只是编写了许多可能在任何阶段发生变化的样板代码,而这种生成的方法可以让我专注于更重要的事情。
是否有人建议使用这样的东西,我可以使用dsl /语言,并且有没有人有这方面的经验?
答案 0 :(得分:5)
我见过一个使用部分类和部分方法的系统,可以在不影响自定义代码的情况下重新生成代码。如果您将完全从Visio状态图生成“规则引擎”。这基本上是糟糕的勒芒工作流程,但很容易修改。 Viso图被导出为XML,使用powershell和T4读入,以生成类。
以上示例是外部DSL。 I.E.在应用程序运行的编程语言之外。另一方面,您可以创建一个内部DSL,它以编程语言实现和使用。
此代码和杂志上的article on DSLSs非常好。
在上面的链接中,Neal Ford向您展示了如何使用流畅的界面在C#中创建内部DSL。
他还没有提到的一件事是你可以将这个属性[EditorBrowsable(EditorBrowsableState.Never)]放在你的方法上,这样它们就不会出现智能感知。这意味着您可以从DSL的用户隐藏类上的非DSL(如果您愿意)方法,使得更流畅的API更容易被发现。
在撰写带TDD的IoC容器时,Daniel Cazzulino可以看到该视频系列中正在编写的流畅界面
关于外部DSL的主题,您还可以选择Oslo (CTP at the moment)这是非常强大的,它能够让您创建可以直接执行的外部DSL,而不是使用代码生成来思考它根本不是一个DSL。
答案 1 :(得分:5)
使用ANTLR可以轻松完成此操作。如果输出足够相似,您可以简单地使用文本模板机制 - 否则它可以生成一个抽象语法树供您遍历。
答案 2 :(得分:1)
我认为你走在正确的轨道上。
在这种情况下我通常做的是设计一种简单的语言来捕获我的需求并为它编写一个LL1(递归下降)解析器。
如果语言必须包含非平凡的C#语法,我可以引用它,或者只是将它包装在我能识别的括号中,然后将其传递给输出代码。
我可以让它生成一个解析树结构,并从中生成3种不同类型的代码,或者我可以让它动态生成代码,或者使用带有3个值的模式变量,或者只是同时写入代码到3个不同的输出文件。
有多种方法可以做到这一点。如果你害怕编写解析器(就像一些程序员那样),那么SO上的其他地方也有很多帮助。