Udostępnij za pośrednictwem


Plik DslDefinition.dsl

W tym temacie opisano strukturę pliku DslDefinition.dsl w projekcie Dsl rozwiązania Narzędzi językowych specyficznych dla domeny, które definiuje język specyficzny dla domeny. Plik DslDefinition.dsl opisuje klasy i relacje języka specyficznego dla domeny wraz z diagramem, kształtami, łącznikami, formatem serializacji i przybornikiem języka specyficznego dla domeny i jego narzędziami do edycji. W rozwiązaniu języka specyficznego dla domeny kod definiujący te narzędzia jest generowany zgodnie z informacjami w pliku DslDefinition.dsl.

Ogólnie rzecz biorąc, do edytowania pliku DslDefinition.dsl używa się Projektant języka specyficznego dla domeny. Jednak jego nieprzetworzona forma to XML i można otworzyć plik DslDefinition.dsl w edytorze XML. Warto zrozumieć, jakie informacje zawiera plik i jak jest on zorganizowany do celów debugowania i rozszerzeń.

Przykłady w tym temacie pochodzą z szablonu rozwiązania Diagram składników. Aby zobaczyć przykład, utwórz rozwiązanie językowe specyficzne dla domeny oparte na szablonie rozwiązania Modele składników. Po utworzeniu rozwiązania plik DslDefinition.dsl pojawi się w Projektant języka specyficznego dla domeny. Zamknij plik, kliknij go prawym przyciskiem myszy w Eksplorator rozwiązań, wskaż polecenie Otwórz za pomocą, kliknij pozycję Edytor XML, a następnie kliknij przycisk OK.

Sekcje pliku DslDefinition.dsl

Element główny to <Dsl>, a jego atrybuty identyfikują nazwę języka specyficznego dla domeny, przestrzeń nazw oraz główne i pomocnicze numery wersji do przechowywania wersji. Schemat DslDefinitionModel definiuje zawartość i strukturę prawidłowego pliku DslDefinition.dsl.

Elementy podrzędne <elementu głównego dsl> są następujące:

Klasy

Ta sekcja definiuje każdą klasę domeny, która generuje klasę w wygenerowanym kodzie.

Relacje

Ta sekcja definiuje każdą relację w modelu. Źródło i element docelowy reprezentują obie strony relacji.

Typy

Ta sekcja definiuje każdy typ i jego przestrzeń nazw. Właściwości domeny mają dwa typy. DomainEnumerations są definiowane w modelu i generują typy w pliku DomainModel.cs. ExternalTypes odwołują się do typów zdefiniowanych gdzie indziej (takich jak String lub Int32) i nie generują żadnych elementów.

Kształty

W tej sekcji zdefiniowano kształty opisujące sposób wyświetlania modelu w projektancie. Te kształty geometryczne są mapowane na klasy w modelu w sekcji Diagram.

Łączniki

W tej sekcji zdefiniowano wygląd łączników wyświetlanych w projektancie. Te geometryczne opisy stylów są mapowane na określone relacje w modelu w sekcji Diagram.

XmlSerializationBehavior

W tej sekcji zdefiniowano schemat serializacji i podano dodatkowe informacje o tym, jak każda klasa jest zapisywana w pliku.

Explorerbehavior

W tej sekcji opisano sposób wyświetlania okna Eksploratora DSL podczas edytowania modelu przez użytkownika.

Połączenie ionBuilders

W tej sekcji zdefiniowano konstruktor połączeń dla każdego narzędzia łącznika (narzędzie do tworzenia linków między dowolnymi dwiema klasami, które można połączyć). Ta sekcja określa, czy można połączyć źródło i klasę docelową.

Diagram

Ta sekcja definiuje diagram i służy do określania właściwości, takich jak kolor tła i klasa główna. (Klasa główna jest klasą domeny reprezentowaną przez diagram jako całość). Sekcja Diagram zawiera również elementy ShapeMap i Połączenie orMap, które określają kształt lub łącznik reprezentujący każdą klasę domeny lub relację.

Projektant

Ta sekcja definiuje projektanta (edytora), który łączy przybornik, ustawienia walidacji, diagram i schemat serializacji. Sekcja Projektant definiuje również klasę główną modelu, która jest zwykle również klasą główną diagramu.

Eksplorator

W tej sekcji opisano zachowanie Eksploratora DSL (zdefiniowane w sekcji XmlSerializationBehavior).

Monikers w pliku DslDefinition.dsl

W całym pliku DslDefinition.dsl można używać elementów monikers do tworzenia odwołań krzyżowych do określonych elementów. Na przykład każda definicja relacji zawiera podsekcję Źródło i podsekcję Docelową. Każda podsekcja zawiera nazwę klasy obiektu, którą można połączyć z tą relacją:

<DomainRelationship ...        Name="LibraryHasMembers" Namespace="ExampleNamespace" >    <Source>      <DomainRole ...>
       <RolePlayer>
         <DomainClassMoniker Name="Library" />
       </RolePlayer>
     </DomainRole>
   </Source>

Zwykle przestrzeń nazw przywoływalnego elementu (w tym przykładzie Library klasa domeny) jest taka sama jak element odwołujący się (w tym przypadku relacja domeny LibraryHasMembers). W takich przypadkach pseudonim musi podać tylko nazwę klasy. W przeciwnym razie należy użyć pełnego formularza /Namespace/Name:

<DomainClassMoniker Name="/ExampleNameSpace/Library" />

System moniker wymaga, aby element równorzędny w drzewie XML miał odrębne nazwy. Z tego powodu błędy walidacji występują, jeśli spróbujesz zapisać definicję języka specyficznego dla domeny, która ma na przykład dwie klasy o tej samej nazwie. Przed zapisaniem pliku DslDefinition.dsl należy zawsze poprawić takie błędy zduplikowane nazwy, aby można było go ponownie załadować później.

Każdy typ ma własny typ moniker: DomainClassMoniker, DomainRelationshipMoniker itd.

Typy

Sekcja Typy określa wszystkie typy, które plik DslDefinition.dsl zawiera jako typy właściwości. Te typy dzielą się na dwa rodzaje: typy zewnętrzne, takie jak System.String, i wyliczone typy.

Typy zewnętrzne

Przykład diagramu składników zawiera listę zestawu standardowych typów pierwotnych, chociaż są używane tylko niektóre z nich.

Każda definicja typu zewnętrznego składa się tylko z nazwy i przestrzeni nazw, takiej jak Ciąg i System:

<ExternalType Name="String" Namespace="System" />

Pełne nazwy typów są używane, zamiast równoważnych słów kluczowych kompilatora, takich jak "ciąg".

Typy zewnętrzne nie są ograniczone do standardowych typów bibliotek.

Wyliczenia

Typowa specyfikacja wyliczenia przypomina ten przykład:

<DomainEnumeration IsFlags="true" Name="PageSort"          Namespace="Fabrikam.Wizard">
  <Literals>
    <EnumerationLiteral Name="Start" Value="1"/>
    <EnumerationLiteral Name="Decision" Value="2"/>
  </Literals>
</DomainEnumeration>

Atrybut IsFlags określa, czy wygenerowany kod jest poprzedzony atrybutem [Flags] Środowiska uruchomieniowego języka wspólnego (CLR), który określa, czy wartości wyliczenia mogą być łączone bitowo. Jeśli ten atrybut ma wartość true, należy określić wartość power-of-two dla wartości literału.

Klasy

Większość elementów w dowolnej definicji języka specyficznego dla domeny jest bezpośrednio lub pośrednio wystąpieniami DomainClassprogramu . Podklasy DomainClass include DomainRelationship, Shape, Connectori Diagram. Sekcja Classes pliku DslDefinition.dsl zawiera listę klas domeny.

Każda klasa ma zestaw właściwości i może mieć klasę bazową. W przykładzie NamedElement diagramu składników jest klasą abstrakcyjną, która ma właściwość, której typem Name jest ciąg:

<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 jest bazą kilku innych klas, takich jak Component, która ma własne właściwości oprócz Name właściwości, którą odziedziczyła z NamedElementklasy . Węzeł podrzędny BaseClass zawiera odwołanie do nazwy moniker. Ponieważ przywoływała klasa znajduje się w tej samej przestrzeni nazw, w moniker wymagany jest tylko jego nazwa:

<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>

Każda klasa domeny (w tym relacje, kształty, łączniki i diagramy) może mieć następujące atrybuty i węzły podrzędne:

  • Identyfikator. Ten atrybut jest identyfikatorem GUID. Jeśli nie podasz wartości w pliku, Projektant języka specyficznego dla domeny utworzy wartość. (Na ilustracjach w tym dokumencie ten atrybut jest zwykle pomijany w celu zaoszczędzenia miejsca).

  • Nazwa i przestrzeń nazw. Te atrybuty określają nazwę i przestrzeń nazw klasy w wygenerowany kod. Razem muszą być unikatowe w języku specyficznym dla domeny.

  • DziedziczenieModyfikator. Ten atrybut jest "abstrakcyjny", "zapieczętowany" lub żaden.

  • Displayname. Ten atrybut to nazwa wyświetlana w oknie Właściwości . Atrybut DisplayName może zawierać spacje i inne znaki interpunkcyjne.

  • GeneratesDoubleDerived. Jeśli ten atrybut ma wartość true, są generowane dwie klasy, a jedna jest podklasą drugiej. Wszystkie wygenerowane metody znajdują się w bazie, a konstruktory znajdują się w podklasie. Ustawiając ten atrybut, można zastąpić dowolną wygenerowaną metodę w kodzie niestandardowym.

  • HasCustomConstructor. Jeśli ten atrybut ma wartość true, konstruktor zostanie pominięty z wygenerowanego kodu, aby można było napisać własną wersję.

  • Atrybuty. Ten atrybut zawiera atrybuty CLR wygenerowanej klasy.

  • Klasa BaseClass. Jeśli określisz klasę bazową, musi być tego samego typu. Na przykład klasa domeny musi mieć inną klasę domeny jako bazę, a kształt przedziału musi mieć kształt przedziału. Jeśli nie określisz klasy bazowej, klasa w wygenerowanym kodzie pochodzi ze standardowej klasy struktury. Na przykład klasa domeny pochodzi z klasy ModelElement.

  • Właściwości. Ten atrybut zawiera właściwości, które są utrzymywane pod kontrolą transakcji i utrwalane podczas zapisywania modelu.

  • ElementMergeDirectives. Każda dyrektywa scalania elementów kontroluje sposób dodawania innego wystąpienia innej klasy do wystąpienia klasy nadrzędnej. Więcej szczegółów na temat dyrektyw scalania elementów można znaleźć w dalszej części tego tematu.

  • Klasa języka C# jest generowana dla każdej klasy domeny wymienionej Classes w sekcji . Klasy języka C# są generowane w pliku Dsl\GeneratedCode\DomainClasses.cs.

Właściwości

Każda właściwość domeny ma nazwę i typ. Nazwa musi być unikatowa w klasie domeny i jej przechodnich bazach.

Typ musi odwoływać się do jednego z wymienionych w Types sekcji . Ogólnie rzecz biorąc, pseudonim musi zawierać przestrzeń nazw.

<DomainProperty Name="Name" DisplayName="Name"  DefaultValue="" Category="" IsElementName="true">
  <Type>
    <ExternalTypeMoniker Name="/System/String" />
  </Type>
</DomainProperty>

Każda właściwość domeny może również mieć następujące atrybuty:

  • IsBrowsable. Ten atrybut określa, czy właściwość jest wyświetlana w oknie Właściwości , gdy użytkownik kliknie obiekt klasy nadrzędnej.

  • IsUIReadOnly. Ten atrybut określa, czy użytkownik może zmienić właściwość w oknie Właściwości , czy za pomocą dekoratora, w którym jest wyświetlana właściwość.

  • Rodzaj. Ten atrybut można ustawić na Wartość Normal, Calculated lub CustomStorage. Jeśli ustawisz ten atrybut na Calculated, musisz podać kod niestandardowy określający wartość, a właściwość będzie tylko do odczytu. Jeśli ustawisz ten atrybut na CustomStorage, musisz podać kod, który pobiera i ustawia wartości.

  • IsElementName. Jeśli ten atrybut ma wartość true, jego wartość jest automatycznie ustawiana na unikatową wartość po utworzeniu wystąpienia klasy nadrzędnej. Ten atrybut można ustawić na wartość true tylko dla jednej właściwości w każdej klasie, która musi mieć typ ciągu. W przykładzie Name diagramu składników właściwość w NamedElement pliku ma IsElementName ustawioną wartość true. Za każdym razem, gdy użytkownik tworzy Component element (który dziedziczy z NamedElement), nazwa jest automatycznie inicjowana na wartość podobną do "Component6".

  • DefaultValue. Jeśli określono ten atrybut, określona wartość jest przypisywana do tego atrybutu dla nowych wystąpień tej klasy. W przypadku IsElementName ustawienia atrybut DefaultValue określa początkową część nowego ciągu.

  • Kategoria to nagłówek, w którym właściwość będzie wyświetlana w oknie Właściwości .

Relacje

Sekcja Relationships zawiera listę wszystkich relacji w języku specyficznym dla domeny. Każdy Domain Relationship element jest binarny i kierowany, łącząc elementy członkowskie klasy źródłowej z elementami członkowskimi klasy docelowej. Klasy źródłowe i docelowe są zazwyczaj klasami domeny, ale relacje z innymi relacjami są również dozwolone.

Na przykład relacja Połączenie ion łączy elementy członkowskie klasy OutPort z członkami klasy InPort. Każde wystąpienie łącza relacji łączy wystąpienie elementu OutPort z wystąpieniem inPort. Ponieważ relacja jest wiele-do-wielu, każda outPort może mieć wiele linków Połączenie ion ze źródłami, a każde wystąpienie InPort może mieć wiele linków Połączenie ion, które go dotyczą.

Role źródłowe i docelowe

Każda relacja zawiera role źródłowe i docelowe, które mają następujące atrybuty:

  • Atrybut RolePlayer odwołuje się do klasy domeny połączonych wystąpień: OutPort dla źródła, InPort dla obiektu docelowego.

  • Atrybut Multiplicity ma cztery możliwe wartości (ZeroMany, ZeroOne, One i OneMany). Ten atrybut odnosi się do liczby łączy tej relacji, które mogą być skojarzone z jednym graczem roli.

  • Atrybut PropertyName określa nazwę używaną w klasie odgrywania roli w celu uzyskania dostępu do obiektów na drugim końcu. Ta nazwa jest używana w szablonie lub kodzie niestandardowym do przechodzenia przez relację. Na przykład PropertyName atrybut roli źródłowej jest ustawiony na Targetswartość . W związku z tym następujący kod będzie działać:

    OutPort op = ...; foreach (InPort ip in op.Targets) ...
    

    Zgodnie z konwencją nazwy właściwości są w liczbie mnogiej, jeśli wielokrotność to ZeroMany lub OneMany.

    Wielokrotność roli odnosi się do liczby ról przeciwnych, które mogą być skojarzone z każdym wystąpieniem tej roli. Na przykład w relacji ComponentHasPorts rola docelowa ma RolePlayer atrybut ustawiony na Port, PropertyName atrybut ustawiony na Składnik i Multiplicity atrybut ustawiony na ZeroOne. W związku z tym odpowiedni kod do użycia tej roli to:

    ComponentPort p = ...; Component c = p.Component; if (c != null) ...
    
  • Name Rola jest nazwą używaną w klasie Relacja, aby odwoływać się do tego końca łącza. Zgodnie z konwencją nazwa roli jest zawsze pojedyncza, ponieważ każde łącze ma tylko jedno wystąpienie na każdym końcu. Poniższy kod będzie działać:

    Connection connectionLink = ...; OutPort op = connectionLink.Source;
    
  • Domyślnie IsPropertyGenerator atrybut ma wartość true. Jeśli ustawiono wartość false, w klasie Role Player nie zostanie utworzona żadna właściwość. (W takim przypadku , op.Targetsna przykład, nie będzie działać). Jednak nadal istnieje możliwość użycia kodu niestandardowego do przechodzenia przez relację lub uzyskania dostępu do samych łączy, jeśli kod niestandardowy jawnie używa relacji:

    OutPort op = ...; foreach (InPort ip in Connection.GetTargets(op)) ...
    foreach (Connection link in Connection.GetLinksToTargets(op)) ...
    

Atrybuty relacji

Oprócz atrybutów i węzłów podrzędnych, które są dostępne dla wszystkich klas, każda relacja ma następujące atrybuty:

  • IsEmbedding. Ten atrybut logiczny określa, czy relacja jest częścią drzewa osadzania. Każdy model musi utworzyć drzewo z osadzanymi relacjami. W związku z tym każda klasa domeny musi być elementem docelowym co najmniej jednej relacji osadzania, chyba że jest ona katalogiem głównym modelu.

  • Elementy ZezwalajDuplikacje. Ten atrybut logiczny, który jest domyślnie fałszywy, ma zastosowanie tylko do relacji, które mają wieloznaczność "wiele" zarówno w źródle, jak i w obiekcie docelowym. Określa, czy użytkownicy języka mogą połączyć jedną parę elementów źródłowych i docelowych przez więcej niż jedno łącze tej samej relacji.

Projektant i karty przybornika

Główną częścią sekcji Projektant pliku DslDefinition.dsl jest element PrzybornikTab. Jeden projektant może mieć kilka z tych elementów, z których każdy reprezentuje sekcję na czele w przyborniku wygenerowanego projektanta. Każdy element ToolboxTab może zawierać co najmniej jeden element ElementTool, Połączenie ionTool lub oba te elementy.

Narzędzia elementów mogą tworzyć wystąpienia określonej klasy domeny. Gdy użytkownik przeciąga narzędzie elementu na diagram, wynik jest określany przez dyrektywy scalania elementów zgodnie z opisem w sekcji dotyczącej dyrektyw scalania elementów w dalszej części tego tematu.

Każde narzędzie połączenia może wywołać określonego konstruktora połączeń. Jeden konstruktor połączeń może utworzyć więcej niż jeden typ relacji, w zależności od tego, gdzie użytkownik klika mysz, zgodnie z opisem w sekcji dotyczącej konstruktorów połączeń.

Żaden typ narzędzia nie tworzy bezpośrednio kształtów ani łączników. Każde wystąpienie klasy domeny lub relacji domeny; Mapowania kształtów i Połączenie or określają, jak jest wyświetlana ta klasa domeny lub relacja domeny.

Ścieżki

Ścieżki domeny są wyświetlane w kilku lokalizacjach w pliku DslDefinition.dsl. Te ścieżki określają serię łączy z jednego elementu w modelu (czyli wystąpienia języka specyficznego dla domeny) do innego. Składnia ścieżki jest prosta, ale szczegółowa.

Ścieżki są wyświetlane w pliku DslDefinition.dsl w <DomainPath>...</DomainPath> tagach. Mimo że ścieżki mogą przechodzić przez wiele linków, większość przykładów w praktyce przechodzi tylko jeden link.

Ścieżka składa się z sekwencji segmentów. Każdy segment jest przeskokiem z obiektu do łącza lub z łącza do obiektu. W związku z tym przeskoki zwykle są alternatywne w długiej ścieżce. Pierwszy przeskok jest z obiektu do łącza, drugi przeskok jest do obiektu na drugim końcu łącza, trzeci przeskok jest do następnego łącza itd. Okazjonalnym wyjątkiem od tej sekwencji jest sytuacja, w której relacja jest źródłem lub elementem docelowym innej relacji.

Każdy segment zaczyna się od nazwy relacji. W przeskoku object-to-link relacja poprzedza kropkę i nazwę właściwości: "Relationship . Property". W przeskoku link-to-object relacja poprzedza wykrzyknik i nazwę roli: "Relationship ! Role".

Przykład diagramu składnika zawiera ścieżkę w elemencie ParentElementPath w elemencie ShapeMap for InPort. Ta ścieżka rozpoczyna się w następujący sposób:

    ComponentHasPorts.Component

W tym przykładzie InPort jest podklasą ComponentPort i ma relację ComponentHasPorts. Właściwość nosi nazwę Component( Składnik).

Podczas pisania języka C# względem tego modelu można przejść przez link w jednym kroku, używając właściwości generowanej przez relację dla każdej z klas, które ma ona związek:

     InPort port; ...  Component c = port.Component;

Należy jednak jawnie wykonać oba przeskoki w składni ścieżki. Ze względu na to wymaganie można łatwiej uzyskać dostęp do linku pośredniego. Poniższy kod kończy przeskok z linku do składnika:

    ComponentHasPorts.Component / ! Component

(Możesz pominąć nazwę relacji, w której jest taka sama jak w poprzednim segmencie).

Dyrektywy scalania elementów

Gdy użytkownik języka przeciąga element z Przybornika na diagram, tworzone jest wystąpienie klasy narzędzia. Ponadto linki są tworzone między tym wystąpieniem a istniejącymi elementami modelu. Niektóre elementy, takie jak składniki lub komentarze, są tworzone, gdy użytkownik języka przeciąga je z przybornika na pustą część diagramu. Inne elementy są tworzone, gdy użytkownik języka przeciąga je na inne elementy hosta. Na przykład obiekt OutPort lub InPort jest tworzony, gdy użytkownik języka przeciąga go na składnik.

Potencjalna klasa hosta, taka jak Component, zaakceptuje nowy element tylko wtedy, gdy klasa hosta ma dyrektywę scalania elementów dla klasy nowego elementu. Na przykład węzeł DomainClass o nazwie ="Składnik" zawiera:

<DomainClass Name="Component" ...> ...
    <ElementMergeDirective>
      <Index>
        <DomainClassMoniker Name="ComponentPort" />
      </Index>
      <LinkCreationPaths>
        <DomainPath>ComponentHasPorts.Ports</DomainPath>
      </LinkCreationPaths>
    </ElementMergeDirective> ...

Pseudonim klasy, który znajduje się w węźle Indeks, odwołuje się do klasy elementu, który można zaakceptować. W tym przypadku ComponentPort jest abstrakcyjną klasą bazową InPort i OutPort. W związku z tym można zaakceptować jeden z tych elementów.

ComponentModel, klasa główna języka, zawiera dyrektywy scalania elementów dla składników i komentarzy. Użytkownik języka może przeciągać elementy dla tych klas bezpośrednio na diagram, ponieważ puste części diagramu reprezentują klasę główną. Jednak model ComponentModel nie ma dyrektywy scalania elementów dla ComponentPort. W związku z tym użytkownik języka nie może przeciągać poleceń InPorts lub OutPorts bezpośrednio na diagram.

Dyrektywa scalania elementów określa, jakie łącza lub linki są tworzone, aby nowy element mógł integrować lub scalać z istniejącym modelem. W przypadku elementu ComponentPort jest tworzone wystąpienie elementu ComponentHasPorts. Parametr DomainPath identyfikuje zarówno relację, jak i właściwość klasy nadrzędnej Ports, do której zostanie dodany nowy element.

Możesz utworzyć więcej niż jeden link w dyrektywie scalania elementów, dołączając więcej niż jedną ścieżkę tworzenia łącza. Jedna ze ścieżek musi być osadzona.

W ścieżce tworzenia łącza można użyć więcej niż jednego segmentu. W tym przypadku ostatni segment definiuje, jaki link należy utworzyć. Wcześniejsze segmenty przechodzą z klasy nadrzędnej do obiektu, z którego ma zostać utworzone nowe łącze.

Można na przykład dodać tę dyrektywę scalania elementu do klasy Component:

<DomainClass Name="Component" ...> ...
  <ElementMergeDirective>
    <Index>
       <DomainClassMoniker Name="Comment"/>
    </Index>
    <LinkCreationPaths>
       <DomainPath>          ComponentModelHasComponents . ComponentModel / !ComponentModel         / ComponentModelHasComments.Comments       </DomainPath>
       <DomainPath>CommentsReferenceComponents.Comments</DomainPath>
    </LinkCreationPaths>
  </ElementMergeDirective>

Użytkownicy języka mogą następnie przeciągnąć komentarz do składnika i automatycznie utworzyć nowy komentarz z linkiem do składnika.

Pierwsza ścieżka tworzenia linku przechodzi z Component do ComponentModel , a następnie tworzy wystąpienie relacji ComponentModelHasCommentsosadzania . Druga ścieżka tworzenia linku tworzy link relacji odwołania KomentarzeReferenceComponents z składnika hosta do nowego komentarza. Wszystkie ścieżki tworzenia linków muszą zaczynać się od klasy hosta i muszą kończyć się linkiem, który krokuje do nowo utworzonej klasy.

Xmlclassdata

Każda klasa domeny (w tym relacje i inne podtypy) może zawierać dodatkowe informacje podane w węźle XmlClassData , które są wyświetlane w XmlSerializationBehavior sekcji pliku DslDefinition.dsl. Te informacje dotyczą konkretnie sposobu przechowywania wystąpień klasy w postaci serializowanej, gdy model jest zapisywany w pliku.

Znaczna część wygenerowanego kodu, który XmlSerializationBehavior ma wpływ, znajduje się w elemecie Dsl\GeneratedCode\Serializer.cs.

Każdy XmlClassData węzeł zawiera następujące węzły podrzędne i atrybuty:

  • Węzeł moniker, który odwołuje się do klasy, do której mają zastosowanie dane.

  • XmlPropertyData dla każdej właściwości zdefiniowanej w klasie.

  • XmlRelationshipData dla każdej relacji źródłowej w klasie . (Relacje mają również własne węzły XmlClassData).

  • Atrybut ciągu TypeName , który określa nazwę klasy pomocnika serializacji w wygenerowany kod.

  • Ciąg ElementName , który określa tag XML serializacji wystąpień tej klasy. Zgodnie z konwencją element Nazwa_elementu jest zwykle taka sama jak nazwa klasy, z wyjątkiem pierwszej litery jest małe litery. Na przykład przykładowy plik modelu rozpoczyna się od następującego:

    <componentModel ...
    
  • MonikerElementName w serializowanych plikach modelu użytkownika. Ten atrybut wprowadza pseudonim, który odwołuje się do tej klasy.

  • MonikerAttributeName, który identyfikuje nazwę atrybutu XML w moniker. W tym fragmentcie serializowanego pliku użytkownika autor języka specyficznego dla domeny zdefiniował nazwę MonikerElementName jako "inPortMoniker" i MonikerAttributeName jako "path":

    <inPortMoniker path="//Component2/InPort1" />
    

Połączenie ionBuilders

Konstruktor połączeń jest definiowany dla każdego narzędzia połączenia. Każdy konstruktor połączeń składa się z co najmniej jednego elementu Link Połączenie Directive, z których każdy zawiera co najmniej jeden element SourceDirective i co najmniej jeden element TargetDirective. Po kliknięciu narzędzia połączenia użytkownik może uruchomić połączenie z dowolnego kształtu zamapowanego na element modelu, który zostanie wyświetlony na liście elementów SourceDirective. Połączenie można następnie wykonać na kształcie zamapowanym na element wyświetlany na liście elementów TargetDirective. Klasa tworzonej relacji zależy od elementu Link Połączenie Directive wyznaczonego przez miejsce rozpoczęcia połączenia.

Xmlpropertydata

Atrybut DomainPropertyMoniker identyfikuje właściwość, do której odwołują się dane. Ten atrybut musi być właściwością otaczającej klasy ClassData.

Atrybut XmlName nadaje odpowiednią nazwę atrybutu, tak jak powinien występować w pliku XML. Zgodnie z konwencją ten ciąg jest taki sam jak nazwa właściwości, z wyjątkiem pierwszej litery jest małą literą.

Domyślnie atrybut Reprezentacja jest ustawiony na Atrybut. Jeśli ustawienie Reprezentacja ma wartość Element, węzeł podrzędny zostanie utworzony w kodzie XML. Jeśli dla opcji Reprezentacja ustawiono wartość Ignoruj, właściwość nie jest serializowana.

Atrybuty IsMonikerKey i IsMonikerQualifier dają właściwości rolę identyfikującą wystąpienia klasy nadrzędnej. Można ustawić właściwość IsMonikerKey na wartość true dla jednej właściwości zdefiniowanej w klasie lub dziedziczonej przez klasę. Ten atrybut identyfikuje pojedyncze wystąpienie klasy nadrzędnej. Właściwość ustawiona na IsMonikerKey jest zwykle nazwą lub innym identyfikatorem klucza. Na przykład Name właściwość string jest kluczem moniker nazwanymElementem i jej klasami pochodnymi. Gdy użytkownik zapisze model do pliku, ten atrybut musi zawierać unikatowe wartości dla każdego wystąpienia, między elementami równorzędnymi w drzewie osadzonych relacji.

W serializowanym pliku modelu pełna moniker elementu jest ścieżką z katalogu głównego modelu w dół drzewa osadzania relacji, cytując klucz moniker w każdym momencie. Na przykład porty InPorts są osadzone w obszarze Składniki, które są z kolei osadzone w katalogu głównym modelu. W związku z tym prawidłowym pseudonimem jest:

<inPortMoniker name="//Component2/InPort1" />

Można ustawić atrybut IsMonikerQualifier dla właściwości string i zapewnić dodatkowy sposób konstruowania pełnej nazwy elementu. Na przykład w pliku DslDefinition.dsl przestrzeń nazw jest kwalifikatorem moniker.

Xmlrelationshipdata

W pliku modelu serializacji łącza (zarówno osadzania, jak i relacji odwołania) są reprezentowane przez węzły podrzędne źródła na końcu relacji. W przypadku osadzania relacji węzeł podrzędny zawiera poddrzewo. W przypadku relacji referencyjnych węzeł podrzędny zawiera pseudonim, który odwołuje się do innej części drzewa.

Atrybut XmlRelationshipData w atrybucie XmlClassData definiuje dokładnie sposób zagnieżdżania węzłów podrzędnych w elemecie źródłowym. Każda relacja, która jest źródłem klasy domeny, ma jeden atrybut XmlRelationshipData .

Atrybut DomainRelationshipMoniker identyfikuje jedną z relacji źródłowych w klasie .

Atrybut RoleElementName nadaje nazwę tagu XML, która otacza węzeł podrzędny w serializowanych danych.

Na przykład plik DslDefinition.dsl zawiera:

<XmlClassData ElementName="component" ...>
  <DomainClassMoniker Name="Component" />
  <ElementData>
    <XmlRelationshipData RoleElementName="ports">
      <DomainRelationshipMoniker Name="ComponentHasPorts" />
    </XmlRelationshipData>

W związku z tym serializowany plik zawiera:

<component name="Component1"> <!-- parent -->
   <ports> <!-- role -->
     <outPort name="OutPort1"> <!-- child element -->
       ...
     </outPort>
   </ports> ...

Jeśli atrybut UseFullForm ma wartość true, zostanie wprowadzona dodatkowa warstwa zagnieżdżania. Ta warstwa reprezentuje samą relację. Atrybut musi być ustawiony na wartość true, jeśli relacja ma właściwości.

<XmlClassData ElementName="outPort">
   <DomainClassMoniker Name="OutPort" />
   <ElementData>
     <XmlRelationshipData UseFullForm="true" RoleElementName="targets">
       <DomainRelationshipMoniker Name="Connection" />
     </XmlRelationshipData>
   </ElementData>
 </XmlClassData>

Serializowany plik zawiera:

<outPort name="OutPort1">  <!-- Parent -->
   <targets>  <!-- role -->
     <connection sourceRoleName="X">  <!-- relationship link -->
         <inPortMoniker name="//Component2/InPort1" /> <!-- child -->
     </connection>
    </targets>
  </outPort>

(Relacja Połączenie ion ma własne dane klasy XML, które udostępniają nazwy elementów i atrybutów).

Jeśli atrybut OmitElement ma wartość true, nazwa roli relacji zostanie pominięta, co skraca serializowany plik i jest jednoznaczne, jeśli dwie klasy nie mają więcej niż jednej relacji. Na przykład:

<component name="Component3">
  <!-- only one relationship could get here: -->
  <outPort name="OutPort1">
     <targets> ...

Serializacja definicji języka specyficznego dla domeny

Plik DslDefinition.dsl jest samym plikiem serializowanym i jest zgodny z definicją języka specyficznego dla domeny. Poniżej przedstawiono kilka przykładów definicji serializacji XML:

  • Dsl to węzeł RootClass i klasa diagramu. DomainClass, DomainRelationship i inne elementy są osadzone w obszarze Dsl.

  • Klasy to RoleElementName relacji między językiem specyficznym dla domeny i domainClass.

<Dsl Name="CmptDsl5" ...>
  <Classes>
    <DomainClass Name="NamedElement" InheritanceModifier="Abstract" ...
  • Atrybut XmlSerializationBehavior jest osadzony w ramach atrybutu Dsl , ale atrybut OmitElement został ustawiony na relacji osadzania. W związku z tym żaden atrybut nie RoleElementName interweniuje. Natomiast atrybut ClassData jest RoleElementName atrybutem relacji osadzania między atrybutem XmlSerializationBehavior a atrybutem XmlClassData .
<Dsl Name="CmptDsl5" ...> ...
  <XmlSerializationBehavior Name="ComponentsSerializationBehavior" >
    <ClassData>
      <XmlClassData ...>...</XmlClassData>
      <XmlClassData ...>...</XmlClassData>
  • Połączenie orHasDecorators to relacja osadzania między Connector i Decorator. UseFullFormzostał ustawiony tak, aby nazwa relacji była wyświetlana z listą właściwości dla każdego łącza z obiektu Połączenie or. Jednak został również ustawiony tak, OmitElement aby nie RoleElementName ujął wielu łączy osadzonych wewnątrz Connectorelementu :
<Connector Name="AssociationLink" ...>
  <ConnectorHasDecorators Position="TargetTop" ...>
    <TextDecorator Name="TargetRoleName"   />
  </ConnectorHasDecorators>
  <ConnectorHasDecorators Position="SourceTop" ...>
    <TextDecorator Name="SourceRoleName"   />
  </ConnectorHasDecorators>
</Connector>

Kształty i Połączenie ory

Definicje kształtów i Połączenie or dziedziczą atrybuty i węzły podrzędne z klas domen oprócz następujących elementów:

  • Color i Line``Style atrybuty.

  • ExposesFillColorAsProperty i kilka podobnych atrybutów. Te atrybuty logiczne tworzą odpowiednią zmienną właściwości przez użytkownika. Ogólnie rzecz biorąc, gdy użytkownik języka kliknie kształt na diagramie, właściwości wyświetlane w oknie Właściwości to wystąpienia klasy domeny, do którego jest mapowany kształt. Jeśli ExposesFillColorAsProperty ustawiono wartość true, zostanie również wyświetlona właściwość samego kształtu.

  • ShapeHasDecorators. Wystąpienie tego atrybutu występuje dla każdego tekstu, ikony lub dekoratora rozwijania/zwijania. (W pliku ShapeHasDecorators DslDefinition.dsl jest relacją z ustawioną UseFullForm wartością true).

Mapy kształtu

Mapy kształtów określają sposób wyświetlania wystąpień danej klasy domeny na ekranie reprezentowanych przez kształt. Mapy kształtów i łączników są wyświetlane w Diagram sekcji pliku DslDefinition.dsl.

Podobnie jak w poniższym przykładzie, ShapeMap elementy mają co najmniej pseudonim klasy domeny, pseudonim kształtu i ParentElementPath elementu:

<ShapeMap>
  <DomainClassMoniker Name="InPort" />
  <ParentElementPath>
    <DomainPath>ComponentHasPorts.Component/!Component</DomainPath>
  </ParentElementPath>
  <PortMoniker Name="InPortShape" />
</ShapeMap>

Podstawową funkcją ParentElementPath elementu jest to, że ta sama klasa obiektów może być wyświetlana jako inny kształt w różnych kontekstach. Jeśli na przykład InPort element może być również osadzony w komentarzu, InPort może być wyświetlany jako inny kształt w tym celu.

Po drugie, ścieżka określa, jak kształt odnosi się do jego elementu nadrzędnego. Nie zdefiniowano struktury osadzania między kształtami w pliku DslDefinition.dsl. Należy wywnioskować strukturę z map kształtów. Element nadrzędny kształtu jest kształtem mapowanym na element domeny, który identyfikuje ścieżka elementu nadrzędnego. W takim przypadku ścieżka identyfikuje składnik, do którego InPort należy. Na innej mapie kształtów klasa Component jest mapowana na element ComponentShape. W związku z tym nowy InPort kształt jest kształtem podrzędnym jego składnika ComponentShape.

Jeśli zamiast tego dołączono kształt InPort do diagramu, ścieżka elementu nadrzędnego musiałaby wykonać kolejny krok do modelu składnika, który jest mapowany na diagram:

ComponentHasPorts . Component / ! Component /    ComponentModelHasComponents . ComponentModel / ! ComponentModel

Katalog główny modelu nie ma mapy kształtu. Zamiast tego katalog główny jest przywołyny bezpośrednio z diagramu, który ma Class element:

<Diagram Name="ComponentDiagram" >
    <Class>
      <DomainClassMoniker Name="ComponentModel" />
    </Class>...

Mapy dekoratora

Mapa dekoratora kojarzy właściwość w zamapowanej klasie z dekoratorem kształtu. Jeśli właściwość jest wyliczonym lub typem logicznym, jego wartość może określić, czy dekorator jest widoczny. Jeśli dekorator jest dekoratorem tekstu, wartość właściwości może być wyświetlana i użytkownik może ją edytować.

Kształt przedziału Mapy

Mapy kształtów przedziału są podtypami map kształtów.

Połączenie or Mapy

Minimalna mapa łącznika odwołuje się do łącznika i relacji:

<ConnectorMap>
  <ConnectorMoniker Name="CommentLink" />
  <DomainRelationshipMoniker Name="CommentsReferenceComponents" />
</ConnectorMap>

mapy Połączenie or mogą również zawierać mapy dekoratora.

Zobacz też