Freigeben über


Anpassen von Dateispeicher und XML-Serialisierung

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

Sie können das Serialisierungsschema anpassen, indem Sie die Einstellungen unter Xml-Serialisierungsverhalten 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 Form-, Verbinder- und Diagrammklassen entsprechen.

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

Hinweis

Wenn Sie das Modell in einem bestimmten Format speichern möchten, es aber nicht aus diesem Formular neu laden müssen, sollten Sie anstelle eines benutzerdefinierten Serialisierungsschemas Textvorlagen verwenden, um eine Ausgabe aus dem Modell zu generieren. Weitere Informationen finden Sie unter Generieren von Code aus einer domänenspezifischen Sprache.

Modell- und Diagrammdateien

Jedes Modell wird in zwei Dateien gespeichert:

  • Die Modelldatei weist einen Namen auf, z Model1.mydsl. B. . In ihr werden die Modellelemente und -beziehungen und deren Eigenschaften gespeichert. Die Dateierweiterung, z .mydsl . B. wird durch die FileExtension-Eigenschaft des Editor-Knotens in der DSL-Definition bestimmt.

  • Die Diagrammdatei weist einen Namen auf, z Model1.mydsl.diagram. B. . In ihr werden die Formen, Verbinder und ihre Positionen, Farben, Linienstärken und andere Details zum Aussehen des Diagramms gespeichert. 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 einer 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 Initiale . der Dateinamenerweiterung ein.

  3. Ändern Sie im Projektmappen-Explorer die Namen der beiden Elementvorlagendateien in DslPackage\ProjectItemTemplates. Diese Dateien weisen Namen im folgenden Format auf:

    myDsl.diagram

    myDsl.myDsl

Das Standardserialisierungsschema

Um ein Beispiel für dieses Thema zu erstellen, wurde die folgende DSL-Definition verwendet.

DSL-Definitionsdiagramm – Stammstrukturmodell

Diese DSL wurde verwendet, um ein Modell zu erstellen, das auf dem Bildschirm wie folgt aussieht.

Stammstrukturdiagramm, 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 weist einen Namen auf, der mit einem Domänenklassennamen identisch ist, mit der Ausnahme, dass der Anfangsbuchstabe ein Kleinbuchstabe 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 Eigenschaftennamens in einen Kleinbuchstaben konvertiert.

  • Jede Beziehung wird als XML-Knoten serialisiert, der innerhalb der Quellseite 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 als Quelle die FamilyTree-Klasse auf. In the XML, the People role is represented with a node named people nested inside the familyTreeModel node.

  • Die Zielseite jeder Einbettungsbeziehung wird als Knoten serialisiert, der unter der Beziehung geschachtelt ist. Der people-Knoten enthält beispielsweise mehrere person-Knoten.

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

    Unter einem person-Knoten kann beispielsweise eine children-Beziehung vorhanden sein. 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 .diagram Datei 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 angegebenen Domäneneigenschaft, die als „Monikerschlüssel“ bezeichnet wird. Der Moniker des Zielelements wird dem Moniker des übergeordneten Elements in der Struktur 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 "Moniker-Schlüssel" im Xml-Serialisierungsverhalten festgelegt true 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 lesbar zu sein, sollten Sie qualifizierte Schlüsselmoniker verwenden. Es ist jedoch möglich, dass der Benutzer mehrere Elemente auf denselben Monikerschlüssel festlegen kann. Doppelte Schlüssel können dazu führen, dass die Datei nicht ordnungsgemäß neu geladen wird. Wenn Sie also eine Domänenklasse definieren, auf die mit qualifizierten Schlüsselmonikern verwiesen wird, sollten Sie Möglichkeiten in Betracht ziehen, um zu verhindern, dass der Benutzer eine Datei mit doppelten Monikern speichern kann.

So legen Sie eine Domänenklasse fest, 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 den Vorgang in dieser Klasse.

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

    Diese Eigenschaft finden Sie unter XML-Serialisierungsverhalten.

So legen Sie eine Domänenklasse fest, auf die von qualifizierten Schlüsselmonikern 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-Serialisierungsverhalten\Klassendaten\<Domänenklasse>\Elementdaten, und wählen Sie dann die Domäneneigenschaft aus.

    2. Legen Sie im Eigenschaftenfenster Is Moniker Key auf true fest.

  • - oder -

    Erstellen Sie mit dem Tool Named Domain Class eine neue Domänenklasse.

    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 mit true initialisiert.

  • - oder -

    Erstellen Sie eine Vererbungsbeziehung zwischen der Domänenklasse und einer anderen Klasse, die über eine Monikerschlüsseleigenschaft verfügt.

Vermeiden doppelter Moniker

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 Ihre DSL beispielsweise über eine Person-Klasse mit einer Eigenschaft „Name“ verfügt, kann der Benutzer die Namen von zwei Elementen auf den gleichen Wert festlegen. 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 den Wert dann 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 Validierung für die DSL. Wählen Sie im DSL-Explorer „Editor\Validierung“ aus, und legen Sie die Uses... -Eigenschaften 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: Der Moniker eines Albums lautet:

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

Dann könnte dies einer der Songs in diesem Album sein:

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

Wenn jedoch stattdessen über die 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, sie nie dem Moniker des übergeordneten Elements vorangestellt wird.

Wenn Sie wissen, dass eine bestimmte Domäneneigenschaft immer über einen eindeutigen Wert innerhalb eines Modells verfügt, können Sie Is Moniker Qualifier für diese Eigenschaft auf true festlegen. Dies bewirkt, dass sie als Qualifizierer verwendet wird, ohne den Moniker des Übergeordneten zu verwenden. Wenn Sie z. B. " Is Moniker Qualifier " und "Is Moniker Key " für die "Title"-Domäneneigenschaft der Albumklasse festlegen, wird der Name oder der Bezeichner des Modells nicht in Monikern für Album und deren eingebettete untergeordnete Elemente verwendet:

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

Anpassen der Struktur des XML-Codes

Erweitern Sie den Knoten XML-Serialisierungsverhalten im DSL-Explorer, um die folgenden Anpassungen vorzunehmen. Erweitern Sie unter einer Domänenklasse den Knoten „Elementdaten“, um die Liste der Eigenschaften und Beziehungen anzuzeigen, die aus dieser Klasse stammen. Wählen Sie eine Beziehung aus, und passen Sie deren Optionen im Eigenschaftenfenster an.

  • Legen Sie Element auslassen 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 Vollständige Form verwenden fest, um die Zielknoten in Knoten einzubetten, die die Beziehungsinstanzen darstellen. Diese Option wird automatisch festgelegt, wenn Sie einer Domänenbeziehung Domäneneigenschaften 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 SieDarstellung = Element so fest, dass eine Domäneneigenschaft als Element anstatt 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.

Größere Anpassungen mithilfe von Programmcode

Sie können Teile von oder alle Serialisierungsalgorithmen ersetzen.

Es wird empfohlen, den Code unter Dsl\Generated Code\Serializer.cs und SerializationHelper.cs zu untersuchen.

So passen Sie die Serialisierung einer bestimmten Klasse an

  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 sich ergebenden Kompilierungsfehler. Kommentare in der Nähe jedes Fehlers erläutern, welchen Code Sie bereitstellen müssen.

So stellen Sie eine eigene Serialisierung für das gesamte Modell bereit

  1. Außerkraftsetzen von Methoden in Dsl\GeneratedCode\SerializationHelper.cs

Hinweis

Ab Visual Studio 2022 17.13 unterstützt die standardmäßige Serialisierungsimplementierung die Serialisierung oder Deserialisierung von benutzerdefinierten Datentypen nicht mehr, da BinaryFormatter sicherheitsrisiken mit BinaryFormatter auftreten.

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 benutzerdefinierten Datentyp in und aus einer Zeichenfolge konvertieren.

Wenn Sie die Abwärtskompatibilität mit älteren Modellen beibehalten müssen, die serialisierung verwendet BinaryFormatter haben, empfiehlt es sich zwar nichtBinaryFormatter, die Verwendung aus Sicherheitsgründen zu verwenden, sie können jedoch eine TypeConverter Deserialisierung der Binärdaten implementieren. 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 Serialization Behavior" einen untergeordneten Knoten für jede Domänenklasse, Beziehung, Form, Verbinder und Diagrammklasse. Unter jedem dieser Knoten befindet sich eine Liste der Eigenschaften und Beziehungen, die aus diesem Element stammen. Beziehungen werden sowohl eigenständig als auch unter ihren Quellklassen dargestellt.

In der folgenden Tabelle werden 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-Serialisierungsverhalten\Klassendaten.

Eigenschaft BESCHREIBUNG
Has Custom Element Schema Gibt an, dass die Domänenklasse über ein benutzerdefiniertes Elementschema verfügt, wenn der Wert TRUE ist.
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 abzurufen.
Domänenklasse Die Domänenklasse, für die dieser Klassendatenknoten gilt. Schreibgeschützt.
Elementname Der XML-Knotenname für Elemente dieser Klasse. Der Standardwert ist eine Version des Domänenklassennamens in Kleinbuchstaben.
Moniker Attribute Name Der Name des Attributs, das in Monikerelementen den Verweis enthält. Wenn das Attribut leer ist, wird der Name der Schlüsseleigenschaft oder der ID verwendet.

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

Der Standardwert ist eine Version des Klassennamens in Kleinbuchstaben mit dem Suffix „Moniker“. Beispiel: personMoniker.
Moniker Type Name Der 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.
Serialize Id TRUE gibt an, dass die Element-GUID in der Datei enthalten ist. Der Wert muss auf "True" festgelegt werden, wenn keine Eigenschaft vorhanden ist, die als Is Moniker Key gekennzeichnet ist, und das DSL definiert Referenzbeziehungen zu dieser Klasse.
Typname Der Name des XML-Typs, der in der XSD-Datei aus der angegebenen Domänenklasse generiert wird.
Notizen Informelle Hinweise, die diesem Element zugeordnet sind

Xml Property Data

XML-Eigenschaftenknoten befinden sich unter den Klassenknoten.

Eigenschaft BESCHREIBUNG
Domäneneigenschaft Die Eigenschaft, für die die XML-Serialisierungskonfigurationsdaten gelten. Schreibgeschützt.
Is Moniker Key Wenn der Wert auf "True" festgelegt 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 zum Erstellen des Qualifizierers in Monikern verwendet. Wenn "false" und "SerializeId" für diese Domänenklasse nicht wahr ist, werden Moniker vom Moniker des übergeordneten Elements in der Einbettungsstruktur qualifiziert.
Darstellung Wenn der Wert auf Attribut festgelegt ist, wird die Eigenschaft als XML-Attribut serialisiert. Wenn der Wert auf "Element" festgelegt ist, wird er als Element serialisiert. Wenn der Wert auf "Ignorieren" festgelegt ist, wird er nicht serialisiert.
Xml Name Der 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.
Hinweise Informelle Hinweise, die diesem Element zugeordnet sind

Xml Role data

Rollendatenknoten befinden sich unter den Quellklassenknoten.

Eigenschaft BESCHREIBUNG
Has Custom 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.
Omit Element Wenn dieser Wert TRUE ist, wird der XML-Knoten,der der Quellrolle entspricht, im Schema ausgelassen.

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.
Role Element Name Gibt den Namen des XML-Elements an, das von der Quellrolle abgeleitet ist. Der Standardwert ist der Name der Rolleneigenschaft.
Use Full Form Wenn dieser Wert TRUE ist, wird jedes Zielelement oder jeder Moniker in einen XML-Knoten eingeschlossen, der die Beziehung darstellt. Dies sollte auf TRUE festgelegt werden, wenn die Beziehung über eigene Domäneneigenschaften verfügt.