刚接触Visual Studio DSL时,被它的基本理论概念迷惑了很长时间, 我的建议是如果能够很快的理解这些概念最好.如果短时间内理解不了就大概了解下这些基础概念,就没有必要为了每一个概念一直深入,搞得自己头疼,倒不如在以后的实践中慢慢深入,理解并加深这些概念.
开发一个DSL需要创建的几个不同的组成部分:域模型,图形符号,工具箱,资源管理器和属性窗口,验证,序列化和部署,打开上一节我们创建的LanguageSm项目中的DslDefinition.dsl文件,可以看到在中心文档区域有左右两部分(两个泳道).
1.左侧是元数据模型(域模型). 也就是域类和域关系.
2.右侧是图形符合,也就是图形元素(Diagram Elements).
其实我们是在用DSL本身在创建DSL,这些描述本身也是在用DSL.
另外,域模型与图形符号之间通过连接器(Connectors)连接,域类之间可以通过关系relationships连接.
域模型 (Domain Model)
每一个DSL的核心都是一个域模型,它定义了语言所代表的各种概念,它们的属性,以及它们之间的关系。在模型驱动开发中,我们的模型要抽象出来,并用DSL的语法描述出来,这也就是用域模型来描述,只要我们有了域模型,工具箱,图形展现都是基于域模型然则创建的。
域模型有两个概念:
1.根域类(root Domain Class)
任何一个DSL有且只有一个根域类,它和你的图形对应,这里说的图形是整个图形的概念。从我们上一节的项目中可以看到,我们创建的时候默认就自动创建了根域类(ExampleModel)和它对应的图形(ExampleShape)。
2.域类(Domain Class)
和根域类不一样,ExampleElement是真正意义上的模型。并且它有一个属性,名称为Name,类型为String.
域关系(domain relationships)
1.嵌入关系(embedding relationship)
嵌入关系表示一个模型能够嵌入在另外一个模型中。在我们的dsl中的可以找到嵌入关系ExampleModelHasElements,把ExampleModel和ExampleElement联系起来(见下图).
在ExampleModel这一端的属性名为Elements,这个集合属性是它包含所有的ExampleElement, 重数为0.*,表达它可以包含零个或者多个ExampleElement, 域角色是指它在这个关系中扮演的角色,角色名你可以通过点击域角色(这条线)在右面的属性里面看到,角色名往往和这一端的源属性名相反,和另外一端的属性名一致。
在ExampleElement这一端的属性名为ExampleModel,表示它所从属的ExampleModel类型,重数为1..1 ,表示它可以并且只可以从属于一个ExampleModel.
简单来说,这个嵌入关系也就表示了在我们的上一切最后运行起来的Dsl中,我们的ExampleModel模型中能够放多个ExampleElement,对于每一个ExampleElement只能从属于一个ExampleModel.
2.引用关系(reference relationship)
在我们的Dsl中看到引用关系ExempleElementReferencesTargets把两个ExampleElements关系起来,表示在两个ExampleElement之间可以建立ExempleElementReferencesTarget关系,引用关系一般有图形表示,所以在设计时通过拖动一条线来把两个模型关系起来,和嵌入关系一样,引用关系也可以设置多重性,表示是否允许和多个模型同时建立引用关系。在我们的例子中源和目标相同,重数为0..*,表示一个ExampleElement可以与多个其它的ExempleElement建立引用关系。
注意这里这不是代表着两个ExampleElement之间可以建立多个重复的引用关系,而是指不同的ExampleElement之间。允许重复的关系需要在关系的属性中设置Allows Duplicates为True.另外很重要的一点,Dsl会对每个域关系生成一个单独的类,模型中建立的每个关系都是这个类的一个实例。我们可以通过属性中的Code下面属性进行设置来控制生成的代码,我们可以设置GeneratesDoubleDerived属性为True,每个关系会生成两个类,父类ExampleModelHasElementsBase包含所有的实现,子类ExampleModelHasElements是一个partial类,所以你可以重载父类的方法来实现你自己的逻辑。另外我们也可以通过这种机制来实现生成的代码里实现某个我们自定义的接口。注意,同样也可以在域类上进行设置。
在这里我觉得有必要对几个概念加强区分一下:
域类---域模型:
域模型包含域类和域关系,域类代表领域中的不同的类型,域关系代表两个域类中的关系信息。
(1) 域模型 --虚线里所所有的
(2) 域类Library
(3) 域类Person
(4) 域关系
(5)重数 * (表示在一个域模型中,一个Library可以有多个Person).
(6)重数 1 (表示一个Person,只能存在于一个Library中).
(7)源角色
(8)目标角色
域属性---属性
在一个域模型中,一个域类可以有一堆域属性,这是和领域挂钩的,是对元数据的描述。但是对于每个域类,我们还可以在DSL设计器中的属性编辑器中,也会列出来一些属性,比如描述,名称等。注意这里的名称属性和这个域类所具有的Name属性是不一样的。这里的属性列出来的是域类的属性,也就是这个域类叫什么名字.
而Dsl图中列出来的是它的领域属性,而且每个域属性其实也是一个元素,所以他本身也会有一些属性,这里的Name其实就是它在图中显示出来的名字。
好了,今天就到这里,先消化下.
作者:孤独侠客(似水流年)
出处:http://lonely7345.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。