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.mydsl
auf. 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.diagram
auf. 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
Öffnen Sie die DSL-Definition. Klicken Sie im DSL-Explorer auf den Editor-Knoten.
Bearbeiten Sie im Eigenschaftenfenster die FileExtension--Eigenschaft. Schließen Sie nicht die anfängliche
.
der Dateinamenerweiterung ein.Ä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.
Dieses DSL wurde verwendet, um ein Modell zu erstellen, das das folgende Erscheinungsbild auf dem Bildschirm hat.
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
undperson
.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 desfamilyTreeModel
-Knotens geschachtelt ist.Die Zielseite jeder Embedding Relationship wird als Knoten serialisiert, der unter der Beziehung geschachtelt ist. Beispielsweise enthält der Knoten
people
mehrereperson
-Knoten.Die Zielseite jeder Verweisbeziehung wird als Moniker serialisiert, der einen Verweis auf das Zielelement codiert.
Beispielsweise kann es unter einem
person
Knoten einechildren
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
Stellen Sie sicher, dass Is Moniker Key für jede Domäneneigenschaft in der Klasse und deren Basisklassen
false
ist.Erweitern Sie im DSL-Explorer XML-Serialisierungsverhalten\Klassendaten\<die Domänenklasse>\Elementdaten.
Vergewissern Sie sich, dass Is Moniker Key für jede Domäneneigenschaft
false
ist.Wenn die Domänenklasse über eine Basisklasse verfügt, wiederholen Sie die Prozedur in dieser Klasse.
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.Erweitern Sie im DSL-Explorer Xml Serialization Behavior\Class Data\<die Domänenklasse>\Element Data, und wählen Sie dann die Domäneneigenschaft aus.
Legen Sie im Eigenschaftenfenster Is Moniker Key auf
true
fest.
-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
true
initialisiert.-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
Legen Sie Is Custom im Knoten für diese Klasse unter XML-Serialisierungsverhalten fest.
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
- Ü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. |