Delen via


File Storage en XML-serialisatie aanpassen

Wanneer de gebruiker een exemplaar opslaat of model, van een domeinspecifieke taal (DSL) in Visual Studio, wordt er een XML-bestand gemaakt of bijgewerkt. Het bestand kan opnieuw worden geladen om het model opnieuw te maken in de Store.

U kunt het serialisatieschema aanpassen door de instellingen onder XML Serialization Behavior in DSL Explorer aan te passen. Er is een knooppunt onder xml-serialisatiegedrag voor elke domeinklasse, eigenschap en relatie. De relaties bevinden zich onder hun bronklassen. Er zijn ook knooppunten die overeenkomen met de klassen shape, verbindingslijn en diagram.

U kunt ook programmacode schrijven voor geavanceerdere aanpassingen.

Notitie

Als u het model in een bepaalde indeling wilt opslaan, maar u het niet opnieuw vanuit dat formulier hoeft te laden, kunt u overwegen tekstsjablonen te gebruiken om uitvoer van het model te genereren in plaats van een aangepast serialisatieschema. Zie Code genereren op basis van een Domain-Specific Languagevoor meer informatie.

Model- en diagrambestanden

Elk model wordt opgeslagen in twee bestanden:

  • Het modelbestand heeft een naam zoals Model1.mydsl. Hierin worden de modelelementen en relaties en hun eigenschappen opgeslagen. De bestandsextensie, zoals .mydsl, wordt bepaald door de eigenschap FileExtension van het Editor-knooppunt in de DSL-definitie.

  • Het diagrambestand heeft een naam zoals Model1.mydsl.diagram. Hiermee worden de vormen, verbindingslijnen en hun posities, kleuren, lijndikten en andere details van het uiterlijk van het diagram opgeslagen. Als de gebruiker een .diagram bestand verwijdert, gaan de essentiële gegevens in het model niet verloren. Alleen de indeling van het diagram gaat verloren. Wanneer het modelbestand wordt geopend, wordt er een standaardset shapes en verbindingslijnen gemaakt.

De bestandsextensie van een DSL wijzigen

  1. Open de DSL-definitie. Klik in DSL Explorer op het knooppunt Editor.

  2. Bewerk in het venster Eigenschappen de eigenschap FileExtension. Neem niet de initiële . van de bestandsnaamextensie op.

  3. Wijzig in Solution Explorer de naam van de twee itemsjabloonbestanden in DslPackage\ProjectItemTemplates. Deze bestanden hebben namen die deze indeling volgen:

    myDsl.diagram

    myDsl.myDsl

Het standaardserialisatieschema

Voor het maken van een voorbeeld voor dit onderwerp is de volgende DSL-definitie gebruikt.

DSL definitiediagram - stamboommodel

Deze DSL werd gebruikt om een model te maken met het volgende uiterlijk op het scherm.

familiestructuurdiagram, werkset en verkenner

Dit model is opgeslagen en opnieuw geopend in de XML-teksteditor:

<?xml version="1.0" encoding="utf-8"?>
<familyTreeModel xmlns:dm0="http://schemas.microsoft.com/VisualStudio/2008/DslTools/Core" dslVersion="1.0.0.0" Id="f817b728-e920-458e-bb99-98edc469d78f" xmlns="http://schemas.microsoft.com/dsltools/FamilyTree">
  <people>
    <person name="Henry VIII" birthYear="1491" deathYear="1547" age="519">
      <children>
        <personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" />
        <personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Mary" />
      </children>
    </person>
    <person name="Elizabeth I" birthYear="1533" deathYear="1603" age="477" />
    <person name="Mary" birthYear="1515" deathYear="1558" age="495" />
  </people>
</familyTreeModel>

Let op de volgende punten over het geserialiseerde model:

  • Elk XML-knooppunt heeft een naam die hetzelfde is als een domeinnaam, behalve dat de eerste letter kleine letters is. Bijvoorbeeld familyTreeModel en person.

  • Domeineigenschappen zoals Name en BirthYear worden geserialiseerd als kenmerken in de XML-knooppunten. Weer wordt het eerste teken van de eigenschapsnaam omgezet naar kleine letters.

  • Elke relatie wordt geserialiseerd als een XML-knooppunt dat is genest binnen het broneinde van de relatie. Het knooppunt heeft dezelfde naam als de eigenschap van de bronrol, maar met een beginteken met kleine letters.

    In de DSL-definitie is bijvoorbeeld een rol met de naam People afkomstig uit de klasse FamilyTree. In de XML wordt de rol Personen weergegeven met een knooppunt met de naam people genest in het familyTreeModel-knooppunt.

  • Het doeleinde van elke insluitingsrelatie wordt geserialiseerd als een knooppunt dat onder de relatie is genest. Het knooppunt people bevat bijvoorbeeld verschillende person knooppunten.

  • Het doeleinde van elke verwijzingsrelatie wordt geserialiseerd als een moniker, waarmee een verwijzing naar het doelelement wordt gecodeerd.

    Er kan bijvoorbeeld een children-relatie zijn onder een person-knooppunt. Dit knooppunt bevat monikers zoals:

    <personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" />
    

Monikers begrijpen

Monikers worden gebruikt om kruisverwijzingen tussen verschillende onderdelen van het model en diagrambestanden weer te geven. Ze worden ook gebruikt in het .diagram-bestand om te verwijzen naar knooppunten in het modelbestand. Er zijn twee vormen van moniker:

  • Id-monikers citeren de GUID van het doelelement. Bijvoorbeeld:

    <personShapeMoniker Id="f79734c0-3da1-4d72-9514-848fa9e75157" />
    
  • Gekwalificeerde sleutelnamen identificeren het doelelement aan de hand van de waarde van een toegewezen domeineigenschap die de naam 'sleutelmoniker' draagt. De naam van het doelelement wordt voorafgegaan door de naam van het bovenliggende element in de hiërarchie van inbeddingsrelaties.

    De volgende voorbeelden zijn afkomstig van een DSL waarin een domeinklasse met de naam Album is, die een insluitingsrelatie heeft met een domeinklasse met de naam Song:

    <albumMoniker title="/My Favorites/Jazz after Teatime" />
    <songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" />
    

    Gekwalificeerde sleutel monikers worden gebruikt als de doelklasse een domeineigenschap heeft waarvoor de optie Is Moniker Key is ingesteld op true in Xml Serialization Behavior. In het voorbeeld is deze optie ingesteld voor domeineigenschappen met de naam 'Titel' in de domeinklassen 'Album' en 'Song'.

Gekwalificeerde sleutelmonikers zijn gemakkelijker te lezen dan ID-monikers. Als u van plan bent om de XML van uw modelbestanden leesbaar te maken voor mensen, kunt u overwegen gekwalificeerde sleutel monikers te gebruiken. Het is echter mogelijk dat de gebruiker meer dan één element instelt om dezelfde monikersleutel te hebben. Dubbele sleutels kunnen ertoe leiden dat het bestand niet correct wordt geladen. Als u daarom een domeinklasse definieert waarnaar wordt verwezen met gekwalificeerde sleutel monikers, moet u overwegen manieren te overwegen om te voorkomen dat de gebruiker een bestand met dubbele monikers opslaat.

Een domeinklasse instellen waarnaar moet worden verwezen door id-monikers

  1. Zorg ervoor dat Is Moniker Key is false voor elke domeineigenschap in de klasse en de bijbehorende basisklassen.

    1. Vouw in DSL Explorer Xml Serialization Behavior\Class Data\<de domeinklasse>\Element Datauit.

    2. Controleer dat de Moniker-sleutel is false voor elke domeineigenschap.

    3. Als de domeinklasse een basisklasse heeft, herhaalt u de procedure in die klasse.

  2. Stel Serialize Id in = true voor de domeinklasse.

    Deze eigenschap vindt u onder xml-serialisatiegedrag.

Een domeinklasse instellen waarnaar moet worden verwezen door gekwalificeerde sleutel monikers

  • Stel Is Moniker Key in voor een domeineigenschap van een bestaande domeinklasse. Het type van de eigenschap moet stringzijn.

    1. Vouw in DSL Explorer Xml Serialization Behavior\Class Data\<de domeinklasse>\Element Datauit en selecteer vervolgens de domeineigenschap.

    2. Stel in het venster Eigenschappen Is Moniker Key in op true.

  • - of -

    Maak een nieuwe domeinklasse aan met behulp van de tool Named Domain Class.

    Met dit hulpprogramma maakt u een nieuwe klasse met een domeineigenschap met de naam Name. De eigenschappen van de domeineigenschap: als elementnaam en als Moniker Key, worden geïnitialiseerd naar true.

  • -of-

    Maak een overnamerelatie van de domeinklasse naar een andere klasse met een moniker-sleuteleigenschap.

Dubbele monikers voorkomen

Als u gekwalificeerde sleutelaanduidingen gebruikt, is het mogelijk dat twee elementen in het gebruikersmodel van een gebruiker dezelfde waarde in de sleuteleigenschap hebben. Als uw DSL bijvoorbeeld een klasse persoon heeft die een eigenschapsnaam heeft, kan de gebruiker de namen van twee elementen instellen op dezelfde. Hoewel het model naar bestand kon worden opgeslagen, werd het niet correct opnieuw geladen.

Er zijn verschillende methoden waarmee u deze situatie kunt voorkomen:

  • Stel de elementnaam = true in voor de sleuteldomeineigenschap. Selecteer de domeineigenschap in het DIAGRAM van de DSL-definitie en stel vervolgens de waarde in het venster Eigenschappen in.

    Wanneer de gebruiker een nieuw exemplaar van de klasse maakt, zorgt deze waarde ervoor dat de domeineigenschap automatisch een andere waarde wordt toegewezen. Het standaardgedrag voegt een getal toe aan het einde van de klassenaam. Dit voorkomt niet dat de gebruiker de naam wijzigt in een duplicaat, maar het helpt in het geval dat de gebruiker de waarde niet instelt voordat het model wordt opgeslagen.

  • Schakel validatie in voor de DSL. Selecteer in DSL Explorer Editor/Validatie en stel de eigenschappen Gebruikt... in op true.

    Er is een automatisch gegenereerde validatiemethode waarmee wordt gecontroleerd op dubbelzinnigheden. De methode bevindt zich in de Load validatiecategorie. Dit zorgt ervoor dat de gebruiker wordt gewaarschuwd dat het mogelijk niet mogelijk is om het bestand opnieuw te openen.

    Voor meer informatie, zie Validatie in een Domain-Specific Taal.

Moniker Paden en Kwalificeerders

Een gekwalificeerde sleutelmoniker eindigt met de monikersleutel en wordt voorafgegaan door de moniker van het bovenliggende element in de insluitboom. Als de moniker van een album bijvoorbeeld het volgende is:

<albumMoniker title="/My Favorites/Jazz after Teatime" />

Dan kan een van de songs in dat album:

<songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" />

Als in plaats daarvan echter naar albums wordt verwezen met id, zijn de monikers als volgt:

<albumMoniker Id="77472c3a-9bf9-4085-976a-d97a4745237c" />
<songMoniker title="/77472c3a-9bf9-4085-976a-d97a4745237c/Hot tea" />

Omdat een GUID uniek is, wordt deze nooit voorafgegaan door de moniker van het bovenliggende element.

Als u weet dat een bepaalde domeineigenschap altijd een unieke waarde binnen een model heeft, kunt u Is Moniker Qualifier instellen op true voor die eigenschap. Dit resulteert in het gebruik als kwalificator, zonder de naam van het bovenliggende element te gebruiken. Als u bijvoorbeeld zowel Is Moniker Qualifier als Is Moniker Key voor de domeineigenschap Titel van de klasse Album instelt, wordt de naam of id van het model niet gebruikt in monikers voor Album en de ingesloten subelementen:

<albumMoniker name="Jazz after Teatime" />
<songMoniker title="/Jazz after Teatime/Hot tea" />

De structuur van de XML aanpassen

Als u de volgende aanpassingen wilt aanbrengen, vouwt u het knooppunt XML-serialisatiegedrag in DSL Explorer uit. Vouw onder een domeinklasse het knooppunt Elementgegevens uit om de lijst met eigenschappen en relaties te zien die zijn afkomstig van deze klasse. Selecteer een relatie en pas de bijbehorende opties aan in het venster Eigenschappen.

  • Stel Element weglaten in op true om de bronrolknoop weg te laten, waardoor alleen de lijst van doelelementen overblijft. U moet deze optie niet instellen als er meer dan één relatie is tussen de bron- en doelklassen.

    <familyTreeModel ...>
      <!-- The following node is omitted by using Omit Element: -->
      <!-- <people> -->
        <person name="Henry VIII" .../>
        <person name="Elizabeth I" .../>
      <!-- </people> -->
    </familyTreeModel>
    
  • Stel Volledig formulier gebruiken in om de doelknooppunten in te sluiten in knooppunten die de relatie-exemplaren vertegenwoordigen. Deze optie wordt automatisch ingesteld wanneer u domeineigenschappen aan een domeinrelatie toevoegt.

    <familyTreeModel ...>
      <people>
        <!-- The following node is inserted by using Use Full Form: -->
        <familyTreeModelHasPeople myRelationshipProperty="x1">
          <person name="Henry VIII" .../>
        </familyTreeModelHasPeople>
        <familyTreeModelHasPeople myRelationshipProperty="x2">
          <person name="Elizabeth I" .../>
        </familyTreeModelHasPeople>
      </people>
    </familyTreeModel>
    
  • Stel de representatie- = in voor element om een domeineigenschap op te slaan als een element, in plaats van als een attribuutwaarde.

    <person name="Elizabeth I" birthYear="1533">
      <deathYear>1603</deathYear>
    </person>
    
  • Als u de volgorde wilt wijzigen waarin kenmerken en relaties worden geserialiseerd, klikt u met de rechtermuisknop op een item onder Elementgegevens en gebruikt u de opdrachten Naar boven of Naar beneden in het menu.

Belangrijke aanpassing met behulp van programmacode

U kunt onderdelen of alle serialisatiealgoritmen vervangen.

We raden u aan de code in Dsl\Generated Code\Serializer.cs en SerializationHelper.cste bestuderen.

De serialisatie van een bepaalde klasse aanpassen

  1. Stel in als Aangepaste in het knooppunt voor die klasse onder Xml-Serialisatiegedrag.

  2. Alle sjablonen transformeren, de oplossing bouwen en de resulterende compilatiefouten onderzoeken. Opmerkingen in de buurt van elke fout leggen uit welke code u moet opgeven.

Uw eigen serialisatie voor het hele model bieden

  1. Methoden overschrijven in Dsl\GeneratedCode\SerializationHelper.cs

Notitie

Vanaf Visual Studio 2022 17.13 ondersteunt de standaard serialisatie-implementatie de serialisatie of deserialisatie van aangepaste gegevenstypen met behulp van BinaryFormatter niet meer vanwege beveiligingsrisico's met BinaryFormatter.

Als u een aangepast gegevenstype gebruikt voor domeineigenschappen, moet u de serialisatiemethoden in de klasse SerializationHelper overschrijven of een TypeConverter implementeren die elk aangepast gegevenstype naar en van een tekenreeks kan converteren.

Hoewel we het gebruik van BinaryFormatter om veiligheidsredenen niet aanbevelen, kunt u een TypeConverter implementeren waarmee de binaire gegevens worden gedeserialiseerd als u achterwaartse compatibiliteit moet behouden met oudere modellen die BinaryFormatter serialisatie hebben gebruikt. Het volgende codefragment fungeert als een sjabloon voor het implementeren van deze compatibiliteit:

class MyCustomDataTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string text)
        {
            // First, try to parse the string as if it were returned by MyCustomDataType.ToString().
            if (MyCustomDataType.TryParse(text, out var custom))
                return custom;

            // Fall back to trying to deserialize the old BinaryFormatter serialization format.
            var decoded = Convert.FromBase64String(text);
            using (var memory = new MemoryStream(decoded, false))
            {
                var binaryFormatter = new BinaryFormatter();
                return binaryFormatter.Deserialize(memory) as MyCustomDataType;
            }
        }

        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is MyCustomDataType custom)
            return custom.ToString();

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

// ...

[TypeConverter(MyCustomDataTypeConverter)]
class MyCustomDataType
{
    // ...
}

Opties in xml-serialisatiegedrag

In DSL Explorer bevat het knooppunt Xml-serialisatiegedrag een onderliggend knooppunt voor elke domeinklasse, relatie, shape, connector en diagramklasse. Onder elk van deze knooppunten bevindt zich een lijst met eigenschappen en relaties die zijn afkomstig van dat element. Relaties worden zowel in hun eigen recht als onder hun bronklassen weergegeven.

De volgende tabel bevat een overzicht van de opties die u in deze sectie van de DSL-definitie kunt instellen. Selecteer in elk geval een element in DSL Explorer en stel de opties in het venster Eigenschappen in.

Xml-klassegegevens

Deze elementen vindt u in DSL Explorer onder Xml Serialization Behavior\Class Data.

Eigenschap Beschrijving
Heeft aangepast elementschema Als Waar is, geeft u aan dat de domeinklasse een aangepast elementschema heeft
Is aangepast Stel de waarde in op True als u uw eigen serialisatie- en deserialisatiecode voor deze domeinklasse wilt schrijven.

Bouw de oplossing en onderzoek de fouten om gedetailleerde instructies te ontdekken.
Domeinklasse Domeinklasse waarop dit klassegegevensknooppunt van toepassing is. Alleen lezen
Elementnaam Xml-knooppuntnaam voor elementen van deze klasse. De standaardwaarde is een versie in kleine letters van de domeinklas naam.
Naam van moniker-kenmerk Naam van het kenmerk dat wordt gebruikt in moniker-elementen om de verwijzing te bevatten. Als dit veld leeg is, wordt de naam van de sleuteleigenschap of -id gebruikt.

In dit voorbeeld is het 'naam': <personMoniker name="/Mike Nash"/>
Naam van moniker-element Naam van het XML-element dat wordt gebruikt voor monikers die verwijzen naar elementen van deze klasse.

De standaardwaarde is een kleine letterversie van de klassenaam, met 'Moniker' als achtervoegsel. Bijvoorbeeld personMoniker.
Naam van monikertype Naam van het xsd-type dat is gegenereerd voor monikers naar elementen van deze klasse. De XSD bevindt zich in Dsl\Generated Code\*Schema.xsd
Id serialiseren Indien waar, wordt de element-GUID opgenomen in het bestand. De waarde moet worden ingesteld op True als er geen eigenschap is die gemarkeerd is als Is Moniker Key en de DSL referentierelaties naar deze klasse definieert.
Typenaam Naam van het XML-type dat is gegenereerd in de xsd van de aangewezen domeinklasse.
Notities Informele notities die aan dit element zijn gekoppeld

Xml-eigenschapsgegevens

Xml-eigenschapsknooppunten worden gevonden onder de klasseknooppunten.

Eigenschap Beschrijving
Domeineigenschap Eigenschap waarop de xml-serialisatieconfiguratiegegevens van toepassing zijn. Alleen lezen.
Is de sleutelwaarde voor moniker Als de waarde is ingesteld op True, wordt de eigenschap gebruikt als de sleutel voor het maken van monikers die verwijzen naar exemplaren van deze domeinklasse.
Is Naam Kwalificatie Als de waarde is ingesteld op True, wordt de eigenschap gebruikt om de kwalificatie in de monikers te maken. Als false en als SerializeId niet waar is voor deze domeinklasse, worden monikers gekwalificeerd door de moniker van het bovenliggende element in de insluitingsstructuur.
Vertegenwoordiging Als de waarde is ingesteld op Kenmerk, wordt de eigenschap geserialiseerd als een XML-kenmerk; als de waarde is ingesteld op Element, wordt deze geserialiseerd als een element; als de waarde is ingesteld op Negeren, wordt deze niet geserialiseerd.
Xml-naam De naam die wordt gebruikt voor het XML-kenmerk of -element dat de eigenschap vertegenwoordigt. De waarde is standaard een versie met kleine letters van de domeineigenschapsnaam.
Notities Informele notities die aan dit element zijn gekoppeld

XML-rolgegevens

Rolgegevensknooppunten worden gevonden onder de bronklasseknooppunten.

Eigenschap Beschrijving
Heeft aangepaste moniker Stel dit in op true als u uw eigen code wilt opgeven voor het genereren en oplossen van monikers die deze relatie doorlopen.

Voor gedetailleerde instructies bouwt u de oplossing en dubbelklikt u op de foutberichten.
Domeinrelatie Hiermee geeft u de relatie op waarop deze opties van toepassing zijn. Alleen lezen.
Element weglaten Indien waar, wordt het XML-knooppunt dat overeenkomt met de bronrol weggelaten uit het schema.

Als er meer dan één relatie is tussen de bron- en doelklassen, maakt dit rolknooppunt onderscheid tussen koppelingen die deel uitmaken van de twee relaties. Daarom raden we u aan deze optie in dit geval niet in te stellen.
Naam van rolelement Hiermee geeft u de naam op van het XML-element dat is afgeleid van de bronrol. De standaardwaarde is de naam van de roleigenschap.
Volledig formulier gebruiken Indien waar, wordt elk doelelement of elke moniker ingesloten in een XML-knooppunt dat de relatie vertegenwoordigt. Dit moet worden ingesteld op true als de relatie een eigen domeineigenschappen heeft.