【问题标题】:Using a DSL to generate C# Code使用 DSL 生成 C# 代码
【发布时间】:2010-10-14 06:11:57
【问题描述】:

目前我正在处理的项目没有完全固定的模型(由于外部影响),因此我希望在编写它们时有一些灵活性。目前,它们在应用程序的三个不同层(数据库、Web api 和客户端)中复制,并且每个层都有相似的逻辑(即验证)。

我想知道是否有一种方法可以让我编写模型文件(比如在 ruby​​ 中),然后让它将该模型转换为必要的 c# 文件。目前,我似乎只是在编写大量可能在任何阶段发生变化的样板代码,而这种生成的方法可以让我专注于更重要的事情。

有没有人推荐这样的东西,我可以使用的 dsl/语言,有没有人有类似的经验?

【问题讨论】:

    标签: c# .net code-generation dsl


    【解决方案1】:

    这可以通过ANTLR 轻松完成。如果输出足够相似,您可以简单地使用文本模板机制——否则它可以生成一个抽象语法树供您遍历。

    【讨论】:

      【解决方案2】:

      我见过一个使用部分类和部分方法来允许重新生成代码而不影响自定义代码的系统。如果您愿意,“规则引擎”完全是从 Visio 状态图生成的。这基本上是糟糕的工作流程,但很容易修改。 Viso 图表导出为 XML,使用 powershell 和 T4 读取以生成类。

      上面的例子是一个外部 DSL。 IE。在运行应用程序的编程语言之外。另一方面,您可以创建一个内部 DSL,该 DSL 在编程语言中实现和使用。

      这个和之前来自 Code-Magazine 的 article on DSLSs 都很好。

      在上面的链接中,Neal Ford 向您展示了如何使用流利的接口在 C# 中创建内部 DSL。

      他还没有提到的一件事是你可以把这个属性 [EditorBrowsable(EditorBrowsableState.Never)] 放在你的方法上,这样它们就不会被智能感知。这意味着您可以对 DSL 的用户隐藏类上的非 DSL(如果您愿意的话)方法,从而使 fluent API 更容易被发现。

      您可以在Daniel Cazzulino 编写的关于使用 TDD 编写 IoC 容器的视频系列中看到流畅的界面

      关于外部 DSL,您还可以选择 Oslo (CTP at the moment),它非常强大,可以让您创建可以直接执行的外部 DSL,而不是使用想到的代码生成根本不是 DSL。

      【讨论】:

      • 很多成熟的编译器都是真正的代码生成器。原来的 C++ 编译器 cfront 直接生成 C 代码,Eiffel 和 Haskell 在转二进制之前也编译成 C。
      • 所有编译器都是代码生成器,它们可能无法生成对人类友好的代码。甚至机器代码指令通常也只是由嵌入在处理器中的微代码解释的高级指令。
      【解决方案3】:

      我认为你在正确的轨道上。

      在这种情况下,我通常会设计一种简单的语言来满足我的需求,并为它编写一个 LL1(递归下降)解析器。

      如果语言中必须包含重要的 C# 语法,我可以引用它,或者将其包裹在我可以识别的括号中,然后将其传递给输出代码。

      我可以让它生成一个解析树结构,并从中生成 3 种不同类型的代码,或者我可以让它动态生成代码,或者使用具有 3 个值的模式变量,或者只是同时编写代码到 3 个不同的输出文件。

      有不止一种方法可以做到这一点。如果您害怕编写解析器(就像某些程序员一样),那么在 SO 的其他地方有很多帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多