Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описывается структура dslDefinition.dsl-файла в проекте Dsl решения средств языка для конкретного домена, определяющего язык, определенный для домена. Файл DslDefinition.dsl описывает классы и связи конкретного домена языка вместе с схемой, фигурами, соединителями, форматом сериализации и панелью элементов языка для конкретного домена и его средствами редактирования. В решении доменного языка код, который определяет эти инструменты, генерируется согласно информации из файла DslDefinition.dsl.
Как правило, конструктор языков для конкретного домена используется для изменения файла DslDefinition.dsl. В необработанном виде файл DslDefinition.dsl представляет собой XML, и его можно открыть в редакторе XML. Это позволит вам понять, какая информация содержится в файле и как она организована в целях отладки и расширения.
Примеры в данном разделе взяты из шаблона решения "Схема компонентов". Чтобы посмотреть пример, создайте решение доменного языка на основе шаблона решения "Модели компонентов". Как только вы создадите решение, в Конструкторе доменного языка появится файл DslDefinition.dsl. Закройте файл, щелкните его правой кнопкой мыши в Обозреватель решений, наведите указатель мыши на "Открыть с помощью", щелкните редактор XML и нажмите кнопку "ОК".
Разделы файла DslDefinition.dsl
Корневой элемент — <dsl>, а его атрибуты определяют имя языка, пространства имен, основного и дополнительного номеров версий для управления версиями. Схема DslDefinitionModel
определяет содержание и структуру действительного файла DslDefinition.dsl.
Дочерние элементы корневого <элемента Dsl> приведены следующим образом:
Классы
В этом разделе определяется каждый класс домена, который генерирует класс в генерируемом коде.
Связи
В этом разделе определяются отношения в модели. Источник и цель представляют собой две стороны отношения.
Типы
В этом разделе определяется каждый тип и его пространство имен. Свойства домена бывают двух типов. DomainEnumerations
определены в модели и создают типы в DomainModel.cs. ExternalTypes
ссылается на типы, определенные в другом месте (например String
, или Int32
) и не создают ничего.
Фигуры
В этом разделе определяются фигуры, которые описывают внешний вид модели в конструкторе. Геометрические фигуры сопоставляются с классами в модели в разделе "Схема".
Соединители
В этом разделе определяется внешний вид соединителей, присутствующих в конструкторе. Описания стиля геометрических фигур сопоставляются с классами в модели в разделе "Схема".
XmlSerializationBehavior
В этом разделе определяется схема сериализации и предоставляется дополнительная информация о порядке сохранения каждого класса в файл.
ExplorerBehavior
В этом разделе определяется, как отображается окно dsL Обозреватель при редактировании модели пользователем.
ConnectionBuilders
В этом разделе определяется построитель соединений для каждого инструмента соединения (инструмент устанавливает связи между любыми двумя классами, которые могут быть соединены). В этом разделе определяется возможность соединения класса источника с классом цели.
Схема
В этом разделе определяется схема, которая используется для указания свойств, таких как цвет фона и корневой класс. (Корневой класс — это класс домена, представленный схемой в целом.) В разделе "Схема" также содержатся элементы ShapeMap и Подключение orMap, которые указывают фигуру или соединитель, представляющий каждый класс домена или связь.
Автор
В этом разделе определяется конструктор (редактор), который объединяет панель элементов, параметры проверки, схему и схему сериализации. Раздел конструктора также определяет корневой класс модели, который обычно является корневым классом схемы.
Обозреватель
Этот раздел определяет поведение dsL Обозреватель (определено в разделе XmlSerializationBehavior).
Моникеры в файле DslDefinition.dsl
В файле DslDefinition.dsl можно использовать моникеры для создания кросс-ссылок на определенные элементы. Например, каждое определение отношения содержит подразделы "Источник" и "Цель". В каждом подразделе содержится моникер класса объекта, который может быть связан с этим отношением:
<DomainRelationship ... Name="LibraryHasMembers" Namespace="ExampleNamespace" > <Source> <DomainRole ...>
<RolePlayer>
<DomainClassMoniker Name="Library" />
</RolePlayer>
</DomainRole>
</Source>
Обычно пространство имен элемента, на который создается ссылка (в данном примере это класс домена Library
), совпадает с пространством имен ссылающегося элемента (в данном случае доменная связь LibraryHasMembers). В подобных случаях моникер должен сообщать только имя класса. Если пространства имен отличаются, необходимо использовать полную форму /Namespace/Name:
<DomainClassMoniker Name="/ExampleNameSpace/Library" />
Система моникеров требует, чтобы одноуровневые элементы в дереве XML имели разные имена. В связи с этим при попытке сохранить определение доменного языка, содержащее, например, два класса с одинаковым именем, возникнут ошибки проверки. Обязательно исправьте такие ошибки с дублирующими именами, прежде чем сохранить файл DslDefinition.dsl, чтобы потом его можно было правильно перезагрузить.
Каждый тип имеет собственный тип моникера: DomainClassMoniker, DomainRelationshipMoniker и т. д.
Типы
В разделе "Типы" определяются все типы, которые файл DslDefinition.dsl содержит в качестве типов и свойств. Эти типы делятся на две категории: внешние типы, такие как System.String, и типы перечисления.
Внешние типы
В примере схемы компонентов приводится список стандартных примитивных типов, хотя используются только некоторые из них.
Каждое определение внешнего типа состоит только из имени и пространства имен, например String и System:
<ExternalType Name="String" Namespace="System" />
Полные имена типов используются вместо эквивалентов ключевых слов компилятора, таких как string.
Внешние типы не ограничиваются стандартной библиотекой типов.
Перечисления
Стандартная спецификация перечислений выглядит следующим образом:
<DomainEnumeration IsFlags="true" Name="PageSort" Namespace="Fabrikam.Wizard">
<Literals>
<EnumerationLiteral Name="Start" Value="1"/>
<EnumerationLiteral Name="Decision" Value="2"/>
</Literals>
</DomainEnumeration>
Атрибут IsFlags
следит за тем, чтобы сгенерированному коду предшествовал атрибут [Flags]
среды CLR, определяющий, могут ли значения перечисления комбинироваться по битам. Если этот атрибут имеет значение true, необходимо указать значения power-of-two для литералов.
Классы
Большинство элементов в любом определении доменного языка прямо или косвенно являются экземплярами DomainClass
. Подклассы DomainClass
включают DomainRelationship
, Shape
, Connector
и Diagram
. В разделе Classes
файла DslDefinition.dsl перечисляются классы доменов.
Каждый класс имеет набор свойств и может иметь базовый класс. В примере схемы компонентов NamedElement
является абстрактным классом со свойством Name
типа строка:
<DomainClass Id="ee3161ca-2818-42c8-b522-88f50fc72de8" Name="NamedElement" Namespace="Fabrikam.CmptDsl5" DisplayName="Named Element" InheritanceModifier="Abstract">
<Properties>
<DomainProperty Id="ef553cf0-33b5-4e34-a30b-cfcfd86f2261" Name="Name" DisplayName="Name" DefaultValue="" Category="" IsElementName="true">
<Type>
<ExternalTypeMoniker Name="/System/String" />
</Type>
</DomainProperty>
</Properties>
</DomainClass>
NamedElement
является основой нескольких других классов, таких как Component
, которые имеют собственные свойства в дополнение к Name
свойству, от которого он наследуется NamedElement
. Дочерний узел BaseClass содержит ссылку на моникер. Так как класс, на который задана ссылка, находится в том же пространстве имен, в моникере указывается только его имя:
<DomainClass Name="Component" Namespace="Fabrikam.CmptDsl5" DisplayName="Component">
<BaseClass>
<DomainClassMoniker Name="NamedElement" />
</BaseClass>
<Properties>
<DomainProperty Name="Kind" DisplayName="Kind" >
<Type>
<ExternalTypeMoniker Name="/System/String" />
</Type>
</DomainProperty>
</Properties>
Каждый класс домена (включая отношения, фигуры, соединители и схемы) может иметь следующие атрибуты и дочерние узлы.
Идентификатор. Этот атрибут является GUID. Если вы не укажете значение в файле, Конструктор доменного языка создаст значение сам. (Для экономии места в иллюстрациях к данному документу этот атрибут обычно опускается.)
Имя и пространство имен. Эти атрибуты указывают имя и пространство имен класса в генерируемом коде. Они должны быть уникальными в пределах доменного языка.
НаследованиеModifier. Данный атрибут является "абстрактным", "запечатанным" или пустым.
Displayname. Этот атрибут — это имя, которое отображается в окне "Свойства ". Атрибут DisplayName может содержать пробелы и другие знаки препинания.
GeneratesDoubleDerived. Если этот атрибут имеет значение true, генерируются два класса, где один является подклассом второго. Все сгенерированные методы включаются в базовый класс, а конструкторы — в подкласс. Настроив данный атрибут, можно переопределить любой сгенерированный метод в пользовательском коде.
HasCustomConstructor. Если этот атрибут имеет значение true, конструктор в генерируемом коде опускается. Это позволяет написать собственную версию кода.
Атрибуты. Это атрибут содержит CLR-атрибуты сгенерированного класса.
BaseClass. Если вы указываете базовый класс, он должен быть того же типа. Например, базовым классом для класса домена должен быть другой класс домена, а для фигуры секции — другая фигура секции. Если базовый класс не указан, то в генерируемом коде используется класс, производный от стандартного класса платформы. Например, класс домена берется из
ModelElement
.Свойства. Данный атрибут содержит свойства, которые поддерживаются элементом управления транзакциями, и запоминается при сохранении модели.
ElementMergeDirectives. Каждая директива слияния элементов контролирует, каким образом другой экземпляр другого класса добавляется к экземпляру родительского класса. Дополнительную информацию о директивах слияния элементов вы найдете ниже.
Класс языка C# генерируется для каждого класса домена, который указан в разделе
Classes
. Классы языка C# создаются в файле Dsl\GeneratedCode\DomainClasses.cs.
Свойства
Каждое свойство домена имеет имя и тип. Имя должно быть уникальным в пределах класса домена и его переходных основ.
Тип должен ссылаться на один из указанных в разделе Types
. Обычно моникер должен содержать пространство имен.
<DomainProperty Name="Name" DisplayName="Name" DefaultValue="" Category="" IsElementName="true">
<Type>
<ExternalTypeMoniker Name="/System/String" />
</Type>
</DomainProperty>
Каждое свойство домена может также иметь следующие атрибуты:
IsBrowsable. Этот атрибут определяет, отображается ли свойство в окне свойств , когда пользователь щелкает объект родительского класса.
IsUIReadOnly. Этот атрибут определяет, может ли пользователь изменить свойство в окне свойств или с помощью декоратора, в котором представлено свойство.
Вроде. Этот атрибут может иметь значение Normal, Calculated или CustomStorage. Если атрибуту присваивается значение Calculated, необходимо создать пользовательский код, который определит значение, а само свойство будет доступно только для чтения. Если атрибуту присваивается значение CustomStorage, необходимо создать код, который будет как получать, так и устанавливать значения.
IsElementName. Если этот атрибут имеет значение true, при создании экземпляра родительского класса ему автоматически присваивается уникальное значение. Этот атрибут может иметь значение true только для одного свойства в каждом классе, причем это свойство должно быть строкового типа. В примере схемы компонентов свойство
Name
вNamedElement
атрибутеIsElementName
имеет значение true. Если пользователь создает элементComponent
(который наследуется отNamedElement
), ему автоматически присваивается имя вида Component6.DefaultValue
. Если данный атрибут указан, то указанное значение назначается этому атрибуту в новых экземплярах данного класса. Если атрибутIsElementName
установлен, то атрибут DefaultValue указывает первоначальную часть новой строки.Категория — это заголовок, в котором свойство будет отображаться в окне "Свойства ".
Связи
В разделе Relationships
перечисляются все отношения в доменном языке. Каждая Domain Relationship
является бинарной и направленной. Она связывает членов класса источника с членами целевого класса. Классы источника и цели обычно являются классами доменов, но связи с другими отношениями также допускаются.
Например, отношение соединения связывает членов класса OutPort с членами класса InPort. Каждый экземпляр связи отношения соединяет экземпляр OutPort с экземпляром InPort. Поскольку отношение относится к типу многий-ко-многим, то каждый экземпляр OutPort может иметь много связей соединения с его источниками, а каждый экземпляр InPort — много связей соединения с целевыми объектами.
Роли источника и цели.
Каждое отношение содержит роли источника и цели со следующими атрибутами.
Атрибут
RolePlayer
ссылается на класс домена связанных экземпляров: OutPort для источника InPort для целевого объекта.У атрибута
Multiplicity
может быть четыре значения (ZeroMany, ZeroOne, One и OneMany). Он указывает количество связей данного отношения, которые могут быть связаны с одним исполнителем роли.Атрибут
PropertyName
указывает имя, которое используется в классе исполнения роли для осуществления доступа к объектам на другом конце. Это имя используется в шаблоне или пользовательском коде для перебора отношения. Например, если атрибутPropertyName
роли источника имеет значениеTargets
, срабатывает следующий код:OutPort op = ...; foreach (InPort ip in op.Targets) ...
Как правило, если атрибут кратности имеет значение ZeroMany или OneMany, имена свойств указываются во множественном числе.
Кратность роли показывает, сколько противоположных ролей могут быть связаны с каждым экземпляром этой роли. Например, если в отношении ComponentHasPorts атрибут
RolePlayer
целевой роли имеет значение Port, атрибутPropertyName
— значение Component, а атрибутMultiplicity
— значение ZeroOne, код для использования этой роли будет выглядеть следующим образом:ComponentPort p = ...; Component c = p.Component; if (c != null) ...
Атрибут роли
Name
— это имя, которое используется в пределах класса отношения для создания ссылок на другой конец связи. Как правило, имя роли всегда указывается в единственном числе, так как каждая связь имеет по одному экземпляру с каждой стороны. Используется следующий код:Connection connectionLink = ...; OutPort op = connectionLink.Source;
По умолчанию атрибут
IsPropertyGenerator
имеет значение true. Если ему будет присвоено значение false, свойство в классе исполнителя роли создано не будет. (В этом случаеop.Targets
, например, работать не будет.) Однако можно использовать пользовательский код для перебора отношения или получения доступа к связям, если пользовательский код использует отношение явно:OutPort op = ...; foreach (InPort ip in Connection.GetTargets(op)) ... foreach (Connection link in Connection.GetLinksToTargets(op)) ...
Атрибуты отношений
В дополнение к атрибутам и дочерним узлам, доступным для всех классов, каждое отношение имеет также следующие атрибуты.
IsEmbedding. Этот логические атрибут определяет, является ли отношение частью дерева внедрения. Каждая модель должна формировать дерево с отношениями внедрения, а каждый класс домена должен быть целевым объектом хотя бы для одного отношения внедрения, если только это не корневой класс модели.
РазрешитьDuplicates. Этот логические атрибут по умолчанию имеет значение false и применяется только к отношениям со значением кратности many как в источнике, так и в цели. Он определяет, могут ли пользователи языка соединять одну пару элементов источника и цели больше чем одной связью в одном и том же отношении.
Конструктор и вкладки панели элементов
Основной частью раздела Конструктора файла DslDefinition.dsl является элементы ToolboxTab . Один конструктор может иметь несколько из этих элементов, каждый из которых представляет заглавный раздел на панели элементов созданного конструктора. Каждый элемент ToolboxTab может содержать один или несколько элементов ElementTool, Подключение ionTool или оба элемента.
Инструменты элементов могут создавать экземпляры определенного класса домена. Когда пользователь перетаскивает элемент на схему, результат определяется директивами слияния элементов, как описано ниже в данном разделе.
Каждый инструмент соединения может вызывать определенный построитель соединения. Один построитель соединения может создавать больше одного типа отношений в зависимости от того, где пользователь щелкает мышкой, как описано в разделе о построителях соединений.
Ни один из типов инструментов не создает фигуры или соединители напрямую. Каждый из них создает класс домена или доменную связь, а затем разметка фигур и соединителей определяет порядок отображения этого класса домена или доменной связи.
Пути
Пути доменов отображаются в файле DslDefinition.dsl в нескольких расположениях. Эти пути указывают на серии связей от одного элемента в модели (т. е. экземпляра доменного языка) к другому. Синтаксис пути простой, но многословный.
Пути отображаются в файле DslDefinition.dsl в тегах <DomainPath>...</DomainPath>
. Несмотря на то, что пути могут проходить через несколько связей, на практике в большинстве случаев каждый путь проходит только через одну.
Путь состоит из последовательности сегментов. Каждый сегмент представляет собой прыжок от объекта к связи или от связи к объекту. В связи с этим прыжки обычно сменяют друг друга, образуя собой длинный путь. Первый прыжок осуществляется от объекта к связи, второй — от объекта к другому концу связи, третий прыжок — к следующей связи и т. д. Редкое исключение в данной последовательности возникает, когда взаимосвязь является источником или целью для другой взаимосвязи.
Каждый сегмент начинается с имени взаимосвязи. В прыжке объекта к ссылке отношение предшествует точке и имени свойства: "Relationship . Property
". В прыжке ссылки к объекту связь предшествует восклицательный знак и имя роли: "Relationship ! Role
".
Пример схемы компонентов содержит путь в элементе ParentElementPath элемента ShapeMap для класса InPort. Этот путь запускается следующим образом:
ComponentHasPorts.Component
В данном примере InPort является подклассом ComponentPort и имеет отношение с классом ComponentHasPorts. Свойство называется Component.
При написании C# для этой модели можно переходить по ссылке на один шаг с помощью свойства, которое связь создает на каждом из классов, которые он связывает:
InPort port; ... Component c = port.Component;
При этом необходимо явно включить оба прыжка в синтаксис пути. Из-за этого требования получение доступа к промежуточной связи можно упростить. Следующий код завершает прыжок из связи в свойство Component.
ComponentHasPorts.Component / ! Component
(Можно опустить имя отношения, если оно такое же, как в предыдущем сегменте.)
Директивы слияния элементов
Когда пользователь языка перетаскивает элемент из панели элементов на схему, создается экземпляр класса инструмента. Кроме того, создаются связи между данным экземпляром и существующими элементами модели. Некоторые элементы, такие как компоненты или комментарии, создаются при перетаскивании пользователя языка из панели элементов в пустую часть схемы. Другие элементы создаются, когда пользователь языка перетаскивает их на другие размещенные элементы. Например, OutPort или InPort создаются, когда пользователь перетаскивает их на компонент.
Потенциальный класс для размещения, такой как Component, принимает новый элемент, только если класс размещения имеет директиву слияния элементов для класса нового элемента. Например, узел DomainClass с параметром Name="Component" содержит следующее:
<DomainClass Name="Component" ...> ...
<ElementMergeDirective>
<Index>
<DomainClassMoniker Name="ComponentPort" />
</Index>
<LinkCreationPaths>
<DomainPath>ComponentHasPorts.Ports</DomainPath>
</LinkCreationPaths>
</ElementMergeDirective> ...
Моникер класса, находящийся под узлом Index, ссылается на класс элемента, который может быть принят. В данном случае, ComponentPort является абстрактным базовым классом элементов InPort и OutPort. Таким образом, любой из этих элементов может быть принят.
ComponentModel, корневой класс языка, имеет директивы слияния элементов для компонентов и комментариев. Пользователь может перетаскивать элементы для этих классов прямо на схему, так как пустые части схемы представляют собой корневой класс. У класса ComponentModel нет директивы слияния элементов для ComponentPort, а значит, пользователь не может перетаскивать элементы InPorts или OutPorts прямо на схему.
Директива слияния элементов определяет, какая связь или связи будут создаваться для того, чтобы новый элемент мог интегрироваться или войти в существующую модель. Для ComponentPort создается экземпляр ComponentHasPorts. DomainPath определяет как взаимосвязь, так и свойство родительского класса Ports, к которому будет добавлен элемент.
Можно создать несколько связей для директивы слияния элементов, включив несколько путей создания связи. Один из путей должен быть встроенным.
В пути создания связи можно использовать несколько сегментов. В данном случае последний сегмент определяет, какую связь необходимо создать. Предшествующие сегменты идут от родительского класса к объекту, из которого будет создана новая связь.
Например, можно добавить эту директиву слияния элементов к классу Component:
<DomainClass Name="Component" ...> ...
<ElementMergeDirective>
<Index>
<DomainClassMoniker Name="Comment"/>
</Index>
<LinkCreationPaths>
<DomainPath> ComponentModelHasComponents . ComponentModel / !ComponentModel / ComponentModelHasComments.Comments </DomainPath>
<DomainPath>CommentsReferenceComponents.Comments</DomainPath>
</LinkCreationPaths>
</ElementMergeDirective>
После этого пользователи смогут перетаскивать комментарий на компонент, в случае чего будет автоматически создан новый комментарий, связанный с компонентом.
Первый путь создания связи идет от Component
к ComponentModel
, а затем создает экземпляр отношения внедрения ComponentModelHasComments
. Второй путь создания связи создает связь отношения со ссылкой CommentsReferenceComponents из элемента размещения Component с новым элементом Comment. Все пути создания связи начинаются с класса размещения и должны заканчиваться на связи, которая переходит к созданному классу.
XmlClassData
Каждый класс домена (включая отношения и другие подтипы) может содержать дополнительную информацию, предоставленную в узле XmlClassData
, который отображается в разделе XmlSerializationBehavior
файла DslDefinition.dsl. Эта информация, в частности, определяет сохранение экземпляров класса в сериализованной форме при сохранении модели в файл.
Большая часть сгенерированного кода, на который влияет XmlSerializationBehavior
, находится в файле Dsl\GeneratedCode\Serializer.cs
.
Каждый узел XmlClassData
включает следующие дочерние узлы и атрибуты.
Узел моникера, ссылающийся на класс, к которому применяются данные.
XmlPropertyData для каждого свойства, определенного в классе.
XmlRelationshipData для каждой связи, исходной в классе. (У отношений также есть собственные узлы XmlClassData.)
Атрибут строки TypeName , определяющий имя вспомогательного класса сериализации в созданном коде.
Строка ElementName , которая определяет XML-тег сериализованных экземпляров этого класса. Как правило, ElementName совпадает с именем класса за тем исключением, что начинается со строчной буквы. Например, файл образца модели начинается следующим образом:
<componentModel ...
MonikerElementName в файлах сериализованной модели пользователя. Данный атрибут вводит моникер, который ссылается на этот класс.
MonikerAttributeName, который определяет имя атрибута XML в моникере. В этом фрагменте сериализованного файла пользователя автор языка, определенного для домена, определяетСя MonikerElementName как inPortMoniker и MonikerAttributeName как path:
<inPortMoniker path="//Component2/InPort1" />
ConnectionBuilders
Построитель соединения определяется для каждого средства соединения. Каждый построитель соединения состоит из одного или нескольких элементов LinkConnectDirective, каждый из которых содержит один или несколько элементов SourceDirective. Выбрав средство соединения, пользователь может начать соединение с любой фигуры, сопоставленной с элементом модели из списка элементов SourceDirective. Соединение может быть завершено на фигуре, сопоставленной с элементом из списка элементов TargetDirective. Создаваемый класс отношения зависит от элемента LinkConnectDirective, который определяется в соответствии с местом создания соединения.
XmlPropertyData
Атрибут DomainPropertyMoniker определяет свойство, к которому ссылаются данные. Данный атрибут должен быть свойством включающего класса ClassData.
Атрибут XmlName предоставляет соответствующее имя атрибута, как оно должно отображаться в XML. Как правило, эта строка совпадает с именем свойства за тем исключением, что начинается со строчной буквы.
По умолчанию атрибут Представления имеет значение Attribute. Если для представления задано значение "Элемент", в XML создается дочерний узел. Если для представления задано значение "Игнорировать", свойство не сериализуется.
Атрибуты IsMonikerKey и IsMonikerQualifier дают свойству роль в определении экземпляров родительского класса. Для одного свойства, определенного в классе или наследуемого классом, можно задать значение true IsMonikerKey . Этот атрибут определяет отдельный экземпляр родительского класса. Свойство, для которого устанавливается значение IsMonikerKey
, обычно является именем или другим ключевым идентификатором. Например, строковое свойство Name
является ключом моникера для NamedElement и его производных классов. Когда пользователь сохраняет модель в файл, этот атрибут должен содержать уникальные значения для каждого экземпляра одноуровневых элементов в дереве отношений внедрения.
В сериализованном файле модели полный моникер элемента представляет собой путь от корня модели вниз по дереву отношений внедрения со ссылками на ключ моникера на каждой точке. Например, элементы InPort внедряются в компоненты, которые, в свою очередь, внедряются в корень модели. Таким образом, правильный моникер выглядит так:
<inPortMoniker name="//Component2/InPort1" />
Атрибут IsMonikerQualifier можно задать для строкового свойства и предоставить дополнительный способ создания полного имени элемента. Например, в файле DslDefinition.dsl пространство имен является квалификатором моникера.
XmlRelationshipData
В сериализованном файле модели связи (как для отношений внедрения, так и для ссылочных отношений) представляются дочерними узлами на стороне источника отношения. В случае отношений внедрения дочерний узел содержит поддерево. В случае ссылочных отношений дочерний узел содержит моникер, который ссылается на другую часть дерева.
Атрибут XmlRelationshipData в атрибуте XmlClassData определяет, как дочерние узлы вложены в исходный элемент. Каждая связь, которая является источником в классе домена, имеет один атрибут XmlRelationshipData .
Атрибут DomainRelationshipMoniker определяет одну из связей, исходных в классе.
Атрибут RoleElementName предоставляет имя тега XML, которое заключает дочерний узел в сериализованные данные.
Например, файл DslDefinition.dsl содержит следующий код:
<XmlClassData ElementName="component" ...>
<DomainClassMoniker Name="Component" />
<ElementData>
<XmlRelationshipData RoleElementName="ports">
<DomainRelationshipMoniker Name="ComponentHasPorts" />
</XmlRelationshipData>
Таким образом, сериализованный файл следующий код:
<component name="Component1"> <!-- parent -->
<ports> <!-- role -->
<outPort name="OutPort1"> <!-- child element -->
...
</outPort>
</ports> ...
Если для атрибута UseFullForm задано значение true, будет введен дополнительный слой вложения. Этот слой представляет собой отношение. Если это отношение имеет свойства, данному атрибуту необходимо присвоить значение true.
<XmlClassData ElementName="outPort">
<DomainClassMoniker Name="OutPort" />
<ElementData>
<XmlRelationshipData UseFullForm="true" RoleElementName="targets">
<DomainRelationshipMoniker Name="Connection" />
</XmlRelationshipData>
</ElementData>
</XmlClassData>
Сериализованный файл содержит следующий код:
<outPort name="OutPort1"> <!-- Parent -->
<targets> <!-- role -->
<connection sourceRoleName="X"> <!-- relationship link -->
<inPortMoniker name="//Component2/InPort1" /> <!-- child -->
</connection>
</targets>
</outPort>
(Отношение соединения имеет собственный XML-класс данных, предоставляющий имена для атрибутов и элемента.)
Если атрибут OmitElement имеет значение true, имя роли связи опущено, что сокращает сериализованный файл и однозначно, если два класса не имеют более одной связи. Например:
<component name="Component3">
<!-- only one relationship could get here: -->
<outPort name="OutPort1">
<targets> ...
Сериализация определения доменного языка.
Файл DslDefinition.dsl сам является сериализованным файлом и соответствует определению доменного языка. Ниже приводятся несколько примеров XML определений сериализации.
Dsl — это узел RootClass и класс схемы. DomainClass, DomainRelationship и другие элементы внедрены в
Dsl
.Классы — это RoleElementName связи между языком конкретного домена и DomainClass.
<Dsl Name="CmptDsl5" ...>
<Classes>
<DomainClass Name="NamedElement" InheritanceModifier="Abstract" ...
- Атрибут XmlSerializationBehavior внедрен в
Dsl
атрибут, но атрибут OmitElement установлен в связи внедрения. Следовательно, атрибутRoleElementName
не внедряется. Напротив, атрибут ClassData являетсяRoleElementName
атрибутом связи внедрения между атрибутом XmlSerializationBehavior и атрибутом XmlClassData .
<Dsl Name="CmptDsl5" ...> ...
<XmlSerializationBehavior Name="ComponentsSerializationBehavior" >
<ClassData>
<XmlClassData ...>...</XmlClassData>
<XmlClassData ...>...</XmlClassData>
- ConnectorHasDecorators является отношением внедрения между
Connector
иDecorator
.UseFullForm
задано значение, чтобы имя связи отображалось со списком свойств для каждой ссылки из объекта Подключение or. При этом атрибутOmitElement
также установлен таким образом, чтобы ни один элементRoleElementName
не включал несколько связей, внедренных вConnector
:
<Connector Name="AssociationLink" ...>
<ConnectorHasDecorators Position="TargetTop" ...>
<TextDecorator Name="TargetRoleName" />
</ConnectorHasDecorators>
<ConnectorHasDecorators Position="SourceTop" ...>
<TextDecorator Name="SourceRoleName" />
</ConnectorHasDecorators>
</Connector>
Фигуры и соединители
Определения фигур и соединителей наследуют атрибуты и дочерние узлы от классов доменов в дополнение к следующим атрибутам:
Атрибуты
Color
иLine``Style
.Предоставляет атрибутыFillColorAsProperty и несколько аналогичных атрибутов. Эти логические атрибуты позволяют пользователю менять соответствующее свойство. Как правило, когда пользователь языка щелкает фигуру на схеме, свойства, отображаемые в окне "Свойства ", относятся к экземпляру класса домена, с которым сопоставляется фигура. Если
ExposesFillColorAsProperty
имеет значение true, также отображается свойство фигуры.ShapeHasDecorator. Экземпляр данного атрибута присутствует в каждом тексте, ярлыке или декораторе расширения и свертывания. (В файле DslDefinition.dsl,
ShapeHasDecorators
является отношением, атрибутUseFullForm
которого имеет значение true.)
Карты фигур
Карты фигур определяют, как экземпляры данного класса домена будут выглядеть на экране. Карты фигур и соединителей отображаются в разделе Diagram
файла DslDefinition.dsl.
Как и в следующем примере, элементы ShapeMap
имеют как минимум моникер класса домена, моникер фигуры и элемент ParentElementPath
:
<ShapeMap>
<DomainClassMoniker Name="InPort" />
<ParentElementPath>
<DomainPath>ComponentHasPorts.Component/!Component</DomainPath>
</ParentElementPath>
<PortMoniker Name="InPortShape" />
</ShapeMap>
Основная функция элемента ParentElementPath
состоит в том, что один и тот же класс объектов может в разном контексте выглядеть по-разному. Например, если InPort
может быть также внедрен в комментарий, в этом качестве InPort
будет отображаться в виде другой фигуры.
Кроме того, путь определяет связь между фигурой и ее родительским объектом. Структура внедрения между фигурами и файлом DslDefinition.dsl не определена и должна выводиться из карт фигур. Родительским объектом фигуры является фигура, сопоставленная с элементом домена, которого определяет путь родительского элемента. В данном случае путь определяет компонент, к которому относится InPort
. В другой карте фигур класс Component сопоставляется с классом с ComponentShape. Следовательно, новая фигура InPort
создает дочернюю фигуру компонента ComponentShape
.
Если вместо этого фигура InPort присоединяется к схеме, пути родительского элемента приходится предпринимать еще один шаг — к модели компонентов, которая сопоставлена со схемой:
ComponentHasPorts . Component / ! Component / ComponentModelHasComponents . ComponentModel / ! ComponentModel
Корень модели не имеет карты фигур. Он ссылается напрямую из схемы, в которой находится элемент Class
:
<Diagram Name="ComponentDiagram" >
<Class>
<DomainClassMoniker Name="ComponentModel" />
</Class>...
Карты декоратора
Карта декоратора объединяет свойство в сопоставленном классе с декоратором в фигуре. Если свойство имеет числовой или логический тип, его значение может определить, будет ли виден декоратор. Если декоратор является текстовым, отображается значение свойства, а пользователь может его редактировать.
Карты фигур секций
Карты фигур секций являются подтипами карт фигур.
Карты соединителей
Минимальная карта соединителя ссылается на соединитель и отношение:
<ConnectorMap>
<ConnectorMoniker Name="CommentLink" />
<DomainRelationshipMoniker Name="CommentsReferenceComponents" />
</ConnectorMap>
Карты соединителей могут также содержать карты декораторов.