Freigeben über


Anpassen der Dateispeicher- und XML-Serialisierung

Wenn der Benutzer eine Instanz oder Modelleiner domänenspezifischen Sprache (DSL) in Visual Studio speichert, wird eine XML-Datei erstellt oder aktualisiert. Die Datei kann neu geladen werden, um das Modell im Store neu zu erstellen.

Sie können das Serialisierungsschema anpassen, indem Sie die Einstellungen unter Xml Serialization Behavior im DSL Explorer anpassen. Es gibt einen Knoten unter Xml Serialization Behavior für jede Domänenklasse, Eigenschaft und Beziehung. Die Beziehungen befinden sich unter ihren Quellklassen. Es gibt auch Knoten, die den Shape-, Verbinder- und Diagrammklassen entsprechen.

Sie können auch Programmcode für erweiterte Anpassungen schreiben.

Anmerkung

Wenn Sie das Modell in einem bestimmten Format speichern möchten, es aber nicht aus diesem Formular neu laden müssen, sollten Sie die Verwendung von Textvorlagen zum Generieren der Ausgabe aus dem Modell anstelle eines benutzerdefinierten Serialisierungsschemas in Betracht ziehen. Weitere Informationen finden Sie unter Generieren von Code für eine domänenspezifische Sprache.

Modell- und Diagrammdateien

Jedes Modell wird in zwei Dateien gespeichert:

  • Die Modelldatei weist einen Namen wie Model1.mydslauf. Es speichert die Modellelemente und -beziehungen und deren Eigenschaften. Die Dateierweiterung wie .mydsl wird durch die FileExtension-eigenschaft des Editor Knotens in der DSL-Definition bestimmt.

  • Die Diagrammdatei weist einen Namen wie Model1.mydsl.diagramauf. Es speichert die Formen, Verbinder und deren Positionen, Farben, Linienstärken und andere Details zur Darstellung des Diagramms. Wenn der Benutzer eine .diagram Datei löscht, gehen die wesentlichen Informationen im Modell nicht verloren. Nur das Layout des Diagramms geht verloren. Wenn die Modelldatei geöffnet wird, wird ein Standardsatz von Shapes und Verbindern erstellt.

So ändern Sie die Dateierweiterung eines DSL

  1. Öffnen Sie die DSL-Definition. Klicken Sie im DSL-Explorer auf den Editor-Knoten.

  2. Bearbeiten Sie im Eigenschaftenfenster die FileExtension--Eigenschaft. Schließen Sie nicht die anfängliche . der Dateinamenerweiterung ein.

  3. Ändern Sie im Projekt-Explorer die Namen der beiden Vorlagendateien für Elemente in DslPackage\ProjectItemTemplates. Diese Dateien weisen Namen auf, die diesem Format folgen:

    myDsl.diagram

    myDsl.myDsl

Das Standard serialisierungsschema

Zum Erstellen eines Beispiels für dieses Thema wurde die folgende DSL-Definition verwendet.

DSL-Definitionsdiagramm - Familienbaummodell

Dieses DSL wurde verwendet, um ein Modell zu erstellen, das das folgende Erscheinungsbild auf dem Bildschirm hat.

Stammbaumdiagramm, Toolbox und Explorer

Dieses Modell wurde gespeichert und dann im XML-Text-Editor erneut geöffnet:

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

Beachten Sie die folgenden Punkte zum serialisierten Modell:

  • Jeder XML-Knoten hat einen Namen, der mit einem Domänenklassennamen identisch ist, mit der Ausnahme, dass der Anfangsbuchstaben Kleinbuchstaben ist. Beispiel: familyTreeModel und person.

  • Domäneneigenschaften wie Name und BirthYear werden als Attribute in den XML-Knoten serialisiert. Auch hier wird das Anfangszeichen des Eigenschaftsnamens in Kleinbuchstaben konvertiert.

  • Jede Beziehung wird als XML-Knoten serialisiert, der innerhalb des Quellendes der Beziehung geschachtelt ist. Der Knoten weist den gleichen Namen wie die Quellrolleneigenschaft auf, jedoch mit einem Kleinbuchstaben als Anfangszeichen.

    In der DSL-Definition weist eine Rolle namens People beispielsweise die FamilyTree-Klasse als Quelle auf. In der XML-Datei wird die People-Rolle durch einen Knoten namens people dargestellt, der innerhalb des familyTreeModel-Knotens geschachtelt ist.

  • Die Zielseite jeder Embedding Relationship wird als Knoten serialisiert, der unter der Beziehung geschachtelt ist. Beispielsweise enthält der Knoten people mehrere person-Knoten.

  • Die Zielseite jeder Verweisbeziehung wird als Moniker serialisiert, der einen Verweis auf das Zielelement codiert.

    Beispielsweise kann es unter einem person Knoten eine children Beziehung geben. Dieser Knoten enthält Moniker wie die folgenden:

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

Grundlegendes zu Monikern

Moniker werden verwendet, um Querverweise zwischen verschiedenen Teilen des Modells und Diagrammdateien darzustellen. Sie werden auch in der datei .diagram verwendet, um auf Knoten in der Modelldatei zu verweisen. Es gibt zwei Formen von Monikern:

  • ID-Moniker zitieren die GUID des Zielelements. Zum Beispiel:

    <personShapeMoniker Id="f79734c0-3da1-4d72-9514-848fa9e75157" />
    
  • Qualifizierte Schlüsselmoniker identifizieren das Zielelement anhand des Werts einer bestimmten Domäneneigenschaft, die als Moniker-Schlüssel bezeichnet wird. Der Name des Zielelements wird dem Namen des übergeordneten Elements im Baum der Einbettungsbeziehungen vorangestellt.

    Die folgenden Beispiele stammen aus einem DSL, in dem es eine Domänenklasse namens "Album" gibt, die eine Einbettungsbeziehung zu einer Domänenklasse namens Song aufweist:

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

    Qualifizierte Schlüsselmoniker werden verwendet, wenn die Zielklasse über eine Domäneneigenschaft verfügt, für die die Option Is Moniker Key in Xml Serialization Behaviorauf true festgelegt ist. Im Beispiel wird diese Option für Domäneneigenschaften namens "Title" in den Domänenklassen "Album" und "Song" festgelegt.

Qualifizierte Schlüsselmoniker sind einfacher zu lesen als ID-Moniker. Wenn Sie beabsichtigen, die XML Ihrer Modelldateien menschlich lesbar zu machen, sollten Sie qualifizierte Schlüsselmoniker verwenden. Es ist jedoch möglich, dass Benutzende mehrere Elemente auf denselben Monikerschlüssel festlegen. Doppelte Schlüssel können dazu führen, dass die Datei nicht ordnungsgemäß neu geladen wird. Wenn Sie daher eine Domänenklasse definieren, auf die mithilfe von qualifizierten Schlüsselmonikern verwiesen wird, sollten Sie möglichkeiten in Betracht ziehen, den Benutzer daran zu hindern, eine Datei mit doppelten Monikern zu speichern.

Festlegen einer Domänenklasse, auf die durch ID-Moniker verwiesen werden soll

  1. Stellen Sie sicher, dass Is Moniker Key für jede Domäneneigenschaft in der Klasse und deren Basisklassen false ist.

    1. Erweitern Sie im DSL-Explorer XML-Serialisierungsverhalten\Klassendaten\<die Domänenklasse>\Elementdaten.

    2. Vergewissern Sie sich, dass Is Moniker Key für jede Domäneneigenschaft false ist.

    3. Wenn die Domänenklasse über eine Basisklasse verfügt, wiederholen Sie die Prozedur in dieser Klasse.

  2. Legen Sie Serialisierungs-ID = true für die Domänenklasse fest.

    Diese Eigenschaft finden Sie unter Xml Serialization Behavior.

Festlegen einer Domänenklasse, auf die durch qualifizierte Schlüsselmoniker verwiesen werden soll

  • Legen Sie Is Moniker Key für eine Domäneneigenschaft einer vorhandenen Domänenklasse fest. Der Typ der Eigenschaft muss string sein.

    1. Erweitern Sie im DSL-Explorer Xml Serialization Behavior\Class Data\<die Domänenklasse>\Element Data, und wählen Sie dann die Domäneneigenschaft aus.

    2. Legen Sie im Eigenschaftenfenster Is Moniker Key auf truefest.

  • -oder-

    Erstellen Sie eine neue Domänenklasse mithilfe des tools Named Domain Class.

    Dieses Tool erstellt eine neue Klasse mit einer Domäneneigenschaft namens Name. Die Eigenschaften Is Element Name und Is Moniker Key dieser Domäneneigenschaft werden auf trueinitialisiert.

  • -oder-

    Erstellen Sie eine Vererbungsbeziehung von der Domänenklasse zu einer anderen Klasse, die über eine Moniker-Schlüsseleigenschaft verfügt.

Doppelte Moniker vermeiden

Wenn Sie qualifizierte Schlüsselmoniker verwenden, ist es möglich, dass zwei Elemente im Modell eines Benutzers den gleichen Wert in der Schlüsseleigenschaft aufweisen könnten. Wenn Ihr DSL beispielsweise über eine Klasse Person verfügt, die einen Eigenschaftsnamen hat, könnte der Benutzer die Namen von zwei Elementen so festlegen, dass es gleich ist. Obwohl das Modell in der Datei gespeichert werden konnte, würde es nicht ordnungsgemäß neu geladen.

Es gibt mehrere Methoden, mit denen Sie diese Situation vermeiden können:

  • Legen Sie Is Element Name = true für die Schlüsseldomäneneigenschaft fest. Wählen Sie die Domäneneigenschaft im DSL-Definitionsdiagramm aus, und legen Sie dann den Wert im Eigenschaftenfenster fest.

    Wenn der Benutzer eine neue Instanz der Klasse erstellt, bewirkt dieser Wert, dass der Domäneneigenschaft automatisch ein anderer Wert zugewiesen wird. Das Standardverhalten fügt am Ende des Klassennamens eine Zahl hinzu. Dies hindert den Benutzer nicht daran, den Namen in ein Duplikat zu ändern. Dies hilft jedoch, wenn der Benutzer den Wert vor dem Speichern des Modells nicht festgelegt hat.

  • Aktivieren Sie die Validierung für das DSL. Wählen Sie im DSL-Explorer „Editor\Validierung“ aus, und legen Sie die Eigenschaft Uses... auf true fest.

    Es gibt eine automatisch generierte Überprüfungsmethode, die auf Mehrdeutigkeiten überprüft. Die Methode befindet sich in der Load-Validierungskategorie. Dadurch wird sichergestellt, dass der Benutzer gewarnt wird, dass es möglicherweise nicht möglich ist, die Datei erneut zu öffnen.

    Weitere Informationen finden Sie unter Validierung in einer domänenspezifischen Sprache.

Monikerpfade und -qualifizierer

Ein qualifizierter Schlüsselmoniker endet mit dem Monikerschlüssel und wird in der Einbettungsstruktur mit dem Moniker seines übergeordneten Elements als Präfix versehen. Beispiel: Wenn der Titel eines Albums lautet:

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

Dann könnte eines der Songs in diesem Album sein:

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

Wenn jedoch stattdessen anhand der ID auf Alben verwiesen wird, würden die Moniker wie folgt aussehen:

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

Beachten Sie, dass eine GUID eindeutig ist und ihr nie der Moniker des übergeordneten Elements vorangestellt wird.

Falls Sie wissen, dass eine bestimmte Domäneneigenschaft immer einen eindeutigen Wert innerhalb eines Modells hat, können Sie Is Moniker Qualifier für diese Eigenschaft auf true festlegen. Dies führt zur Verwendung als Qualifizierer, ohne dabei den Moniker des übergeordneten Elements zu verwenden. Wenn Sie beispielsweise Is Moniker Qualifier und Is Moniker Key für die title-Domäneneigenschaft der album-Klasse festlegen, wird der Name oder Bezeichner des Modells nicht in Monikern für „album“ und die eingebetteten untergeordneten Elemente verwendet:

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

Anpassen der Struktur des XML-Codes

Um die folgenden Anpassungen vorzunehmen, erweitern Sie den Xml Serialization Behavior Knoten im DSL-Explorer. Erweitern Sie unter einer Domänenklasse den Knoten "Elementdaten", um die Liste der Eigenschaften und Beziehungen anzuzeigen, die an dieser Klasse stammen. Wählen Sie eine Beziehung aus, und passen Sie die zugehörigen Optionen im Eigenschaftenfenster an.

  • Legen Sie Omit Element auf „true“ fest, um den Quellrollenknoten auszulassen, sodass nur die Liste der Zielelemente übrig bleibt. Sie sollten diese Option nicht festlegen, wenn es mehr als eine Beziehung zwischen der Quell- und Zielklasse gibt.

    <familyTreeModel ...>
      <!-- The following node is omitted by using Omit Element: -->
      <!-- <people> -->
        <person name="Henry VIII" .../>
        <person name="Elizabeth I" .../>
      <!-- </people> -->
    </familyTreeModel>
    
  • Legen Sie Use Full Form fest, um die Zielknoten in Knoten einzubetten, die die Beziehungsinstanzen darstellen. Diese Option wird automatisch festgelegt, wenn Sie domäneneigenschaften zu einer Domänenbeziehung hinzufügen.

    <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>
    
  • Legen Sie Representation = Element- so fest, dass eine Domäneneigenschaft als Element und nicht als Attributwert gespeichert wird.

    <person name="Elizabeth I" birthYear="1533">
      <deathYear>1603</deathYear>
    </person>
    
  • Um die Reihenfolge zu ändern, in der Attribute und Beziehungen serialisiert werden, klicken Sie mit der rechten Maustaste auf ein Element unter „Elementdaten“, und verwenden Sie die Menübefehle Nach oben oder Nach unten.

Wichtige Anpassungen mithilfe von Programmcode

Sie können Teile oder alle Serialisierungsalgorithmen ersetzen.

Es wird empfohlen, den Code in Dsl\Generated Code\Serializer.cs und SerializationHelper.cszu studieren.

Anpassen der Serialisierung einer bestimmten Klasse

  1. Legen Sie Is Custom im Knoten für diese Klasse unter XML-Serialisierungsverhalten fest.

  2. Transformieren Sie alle Vorlagen, erstellen Sie die Lösung, und untersuchen Sie die resultierenden Kompilierungsfehler. Kommentare in der Nähe jedes Fehlers erläutern, welchen Code Sie bereitstellen müssen.

Bereitstellen einer eigenen Serialisierung für das gesamte Modell

  1. Überschreiben von Methoden in Dsl\GeneratedCode\SerializationHelper.cs

Anmerkung

Ab Visual Studio 2022 17.13 unterstützt die standardmäßige Serialisierungsimplementierung die Serialisierung oder Deserialisierung von benutzerdefinierten Datentypen mit BinaryFormatter aufgrund Sicherheitsrisiken mit BinaryFormatternicht mehr.

Wenn Sie einen benutzerdefinierten Datentyp für domäneneigenschaften verwenden, müssen Sie entweder die Serialisierungsmethoden in der SerializationHelper-Klasse außer Kraft setzen oder einen TypeConverter implementieren, der jeden benutzerdefinierten Datentyp in und aus einer Zeichenfolge konvertieren kann.

Aus Sicherheitsgründen wird die Verwendung von BinaryFormatter nicht empfohlen. Wenn Sie jedoch die Abwärtskompatibilität mit älteren Modellen, die BinaryFormatter-Serialisierung verwendet haben, beibehalten müssen, können Sie eine TypeConverter implementieren, die die Binärdaten deserialisiert. Der folgende Codeausschnitt dient als Vorlage für die Implementierung dieser Kompatibilität:

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
{
    // ...
}

Optionen im Xml-Serialisierungsverhalten

Im DSL-Explorer enthält der Knoten "XML-Serialisierungsverhalten" einen untergeordneten Knoten für jede einzelne Domänenklasse, für jede Beziehung, für jede Form, für jeden Verbinder und für jede Diagrammklasse. Unter jedem dieser Knoten handelt es sich um eine Liste von Eigenschaften und Beziehungen, die an diesem Element stammen. Beziehungen werden sowohl eigenständig als auch unter ihren Ursprungsklassen dargestellt.

In der folgenden Tabelle sind die Optionen zusammengefasst, die Sie in diesem Abschnitt der DSL-Definition festlegen können. Wählen Sie in jedem Fall ein Element im DSL Explorer aus, und legen Sie die Optionen im Eigenschaftenfenster fest.

Xml-Klassendaten

Diese Elemente befinden sich im DSL-Explorer unter Xml Serialization Behavior\Class Data.

Eigentum Beschreibung
Verfügt über ein benutzerdefiniertes Elementschema Wenn True, gibt an, dass die Domänenklasse über ein benutzerdefiniertes Elementschema verfügt.
Is Custom Legen Sie den Wert auf True fest, wenn Sie ihren eigenen Serialisierungs- und Deserialisierungscode für diese Domänenklasse schreiben möchten.

Erstellen Sie die Lösung, und untersuchen Sie die Fehler, um detaillierte Anweisungen zu ermitteln.
Domänenklasse Domänenklasse, auf die dieser Klassendatenknoten angewendet wird. Schreibgeschützt.
Element Name Xml-Knotenname für Elemente dieser Klasse. Der Standardwert ist eine Kleinschreibung des Domänenklassennamens.
Moniker Attribute Name Name des Attributs, das in Monikerelementen den Verweis enthalten soll. Wenn es leer ist, wird der Name der Schlüsseleigenschaft oder ID verwendet.

In diesem Beispiel ist es "name": <personMoniker name="/Mike Nash"/>
Moniker Element Name Name des xml-Elements, das für Moniker verwendet wird, die auf Elemente dieser Klasse verweisen.

Der Standardwert ist eine Kleinbuchstabenversion des Klassennamens mit dem Suffix "Moniker". Beispiel: personMoniker.
Moniker-Typname Name des XSD-Typs, der für Moniker für Elemente dieser Klasse generiert wird. Der XSD-Typ befindet sich in Dsl\Generated Code\*Schema.xsd.
Serialisieren der ID Wenn True, ist die Element-GUID in der Datei enthalten. Der Wert muss auf true festgelegt werden, wenn keine Eigenschaft vorhanden ist, die mit Is Moniker Key gekennzeichnet ist, und die domänenspezifische Sprache definiert Verweisbeziehungen zu dieser Klasse.
Typname Name des xml-Typs, der in der xsd aus der angegebenen Domänenklasse generiert wurde.
Notes Informelle Notizen, die diesem Element zugeordnet sind

Xml-Eigenschaftsdaten

Xml-Eigenschaftsknoten werden unter den Klassenknoten gefunden.

Eigentum Beschreibung
Domain Property Eigenschaft, auf die die XML-Serialisierungskonfigurationsdaten angewendet werden. Schreibgeschützt.
Is Moniker Key Wenn der Wert auf Truefestgelegt ist, wird die Eigenschaft als Schlüssel zum Erstellen von Monikern verwendet, die auf Instanzen dieser Domänenklasse verweisen.
Is Moniker Qualifier Wenn der Wert auf true festgelegt ist, wird die Eigenschaft zur Erstellung des Qualifizierers in Monikern verwendet. Wenn „false“ festgelegt ist und „SerializeId“ für diese Domänenklasse nicht auf „true“ festgelegt ist, werden Moniker vom Moniker des übergeordneten Elements in der EInbettungsstruktur qualifiziert.
Vertretung Wenn der Wert auf Attributfestgelegt ist, wird die Eigenschaft als XML-Attribut serialisiert. wenn der Wert auf Elementfestgelegt ist, wird er als Element serialisiert; wenn der Wert auf Ignorefestgelegt ist, wird er nicht serialisiert.
Xml Name Name, der für das XML-Attribut oder -Element verwendet wird, das die Eigenschaft darstellt. Standardmäßig ist der Wert eine Kleinschreibung des Domäneneigenschaftsnamens.
Notes Informelle Notizen, die diesem Element zugeordnet sind

XML-Rolle-Daten

Rollendatenknoten befinden sich unter den Quellklassenknoten.

Eigentum Beschreibung
Hat benutzerdefinierten Moniker Legen Sie diesen Wert auf "true" fest, wenn Sie Ihren eigenen Code zum Generieren und Auflösen von Monikern bereitstellen möchten, die diese Beziehung durchlaufen.

Um ausführliche Anweisungen zu erhalten, erstellen Sie die Projektmappe, und doppelklicken Sie dann auf die Fehlermeldungen.
Domänenbeziehung Gibt die Beziehung an, für die diese Optionen gelten. Schreibgeschützt.
Element auslassen Wenn true, wird der XML-Knoten, der der Quellrolle entspricht, aus dem Schema weggelassen.

Wenn es mehrere Beziehungen zwischen der Quell- und Zielklasse gibt, unterscheidet dieser Rollenknoten zwischen Verknüpfungen, die zu den beiden Beziehungen gehören. Daher wird empfohlen, diese Option in diesem Fall nicht festzulegen.
Rollenelementname Gibt den Namen des XML-Elements an, das von der Quellrolle abgeleitet wird. Der Standardwert ist der Name der Rolleneigenschaft.
Vollformular verwenden Wenn wahr, wird jedes Zielelement oder jeder Bezeichner in einen XML-Knoten eingeschlossen, der die Beziehung darstellt. Dies sollte auf "true" festgelegt werden, wenn die Beziehung über eigene Domäneneigenschaften verfügt.