Business Objects的领域特定语言?

时间:2009-02-21 19:10:42

标签: language-agnostic code-generation

我正在考虑编写特定于域的语言(DSL)来建模业务对象。 DSL将不会被执行,而是由基于模板的代码生成器(可能是CodeSmith)使用它来生成.NET& SQL。

DSL需要支持以下元素的定义:

  • 课程(姓名和说明)
  • 属性(名称,友好名称,类型,null / not null)
  • 简单验证(必需,正则表达式,范围等)
  • 班级之间的关系(1对1,1对多,多对多)
  • 继承(好的,可能在版本2中)

以下是DSL代码的简单示例:

Class: Insured
  Desc: "Represents a person covered by an insurance policy"
  Prop: FirstName, "First Name", String(20), not null
  Prop: LastName, "Last Name", String(20), not null
  Prop: MailAddress, "Mailing Address", Address, not null
  Prop: SSN, "Social Security Number", String(9), null      
  Rule: RegEx, SSN, ^\d{9}$

Class: Address
  Prop: Line1, "Line 1", String(30), not null
  Prop: City, "City", String(30), not null
  Prop: State, "State", String(2), not null
  ...

为了保持DSL简单,更复杂的验证规则将以目标语言编码。当前的计划是使生成的代码不受限制,并将更复杂的规则添加到子类。

有没有人写过类似的东西?您能提供类似解决方案的任何提示或链接吗?

4 个答案:

答案 0 :(得分:2)

将您呈现的结构自动转换为XML非常容易。从那里,我想可以通过XSLT或XQuery将某种转换写入您想要的任何最终结果。我编写了一个名为CodeGenUtils的Visual Studio加载项,以便于进行转换。

如果您真的想要编写自己的解析器,我建议您查看现有的文本DSL解决方案,例如JetBrains MPS

答案 1 :(得分:1)

建议你看看OSLO,如果只是为了避免重新发明它。

答案 2 :(得分:1)

我有一个名为bdUnit的项目,我使用Oslo框架的一部分创建了一个DSL,用于将用户故事建模为C#接口和单元测试。

示例输入的一部分:

begin story "AUserStory":
begin setup 
    @Person to have a ~Spouse(@Person) 
            ~IsActive(true) 
            ~Age(0) 
            ~IsDead(false) 
            and several ~Children(@Person)
            and a ~Location(@Location)
        I want a @Person to be able to #Kill another @Person
        I want a @Person to be able to #Marry another @Person
        I want to be able to #Find all @Person
    @Location to have a ~Latitude(0.0)
            and a ~Longitude(0.0)
end setup

相应生成的C#代码:

[PluginFamily("bdUnit")]
public interface IPerson
{
    IPerson Spouse { get; set; }
    bool IsActive { get; set; }
    int Age { get; set; }
    bool IsDead { get; set; }
    IList<IPerson> Children { get; set; }
    ILocation Location { get; set; }
    void Kill(IPerson user);
    void Marry(IPerson user);
    void Find();
}

[PluginFamily("bdUnit")]
public interface ILocation
{
    decimal Latitude { get; set; }
    decimal Longitude { get; set; }
}

我在dll中编译接口和测试,因此它们是“禁止的”。这些接口只能在继承类中实现。然后我使用StructureMap将所需的依赖项注入单元测试。

答案 3 :(得分:0)

嗯,它来自Java世界,但是使用Eclipse项目TMF Xtext这样的任务将在几分钟内完成。 看看他们的主页,我提供了非常相似的例子。