我正在考虑编写特定于域的语言(DSL)来建模业务对象。 DSL将不会被执行,而是由基于模板的代码生成器(可能是CodeSmith)使用它来生成.NET& SQL。
DSL需要支持以下元素的定义:
以下是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简单,更复杂的验证规则将以目标语言编码。当前的计划是使生成的代码不受限制,并将更复杂的规则添加到子类。
有没有人写过类似的东西?您能提供类似解决方案的任何提示或链接吗?
答案 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这样的任务将在几分钟内完成。 看看他们的主页,我提供了非常相似的例子。