Dostosowywanie przechowywania plików i serializacji XML
Gdy użytkownik zapisze wystąpienie lub model języka specyficznego dla domeny (DSL) w programie Visual Studio, zostanie utworzony lub zaktualizowany plik XML. Plik można ponownie załadować, aby odtworzyć model w Sklepie.
Schemat serializacji można dostosować, dostosowując ustawienia w obszarze Zachowanie serializacji XML w Eksploratorze DSL. Istnieje węzeł w obszarze Zachowanie serializacji XML dla każdej klasy domeny, właściwości i relacji. Relacje znajdują się w ramach ich klas źródłowych. Istnieją również węzły odpowiadające klasom kształtu, łącznika i diagramu.
Możesz również napisać kod programu w celu bardziej zaawansowanego dostosowywania.
Uwaga
Jeśli chcesz zapisać model w określonym formacie, ale nie musisz go ponownie ładować z tego formularza, rozważ użycie szablonów tekstowych do wygenerowania danych wyjściowych z modelu zamiast niestandardowego schematu serializacji. Aby uzyskać więcej informacji, zobacz Generowanie kodu z języka specyficznego dla domeny.
Pliki modelu i diagramu
Każdy model jest zapisywany w dwóch plikach:
Plik modelu ma nazwę taką jak
Model1.mydsl
. Przechowuje elementy modelu i relacje oraz ich właściwości. Rozszerzenie pliku, takie jak.mydsl
, jest określane przez właściwość FileExtension węzła Edytor w definicji DSL.Plik diagramu ma nazwę taką jak
Model1.mydsl.diagram
. Przechowuje kształty, łączniki i ich pozycje, kolory, grubość linii i inne szczegóły wyglądu diagramu. Jeśli użytkownik usunie.diagram
plik, podstawowe informacje w modelu nie zostaną utracone. Utracono tylko układ diagramu. Po otwarciu pliku modelu zostanie utworzony domyślny zestaw kształtów i łączników.
Aby zmienić rozszerzenie pliku DSL
Otwórz definicję DSL. W Eksploratorze DSL kliknij węzeł Edytor.
W okno Właściwości edytuj właściwość FileExtension. Nie dołączaj początkowego
.
rozszerzenia nazwy pliku.W Eksplorator rozwiązań zmień nazwę dwóch plików szablonów elementów w pliku DslPackage\ProjectItemTemplates. Te pliki mają nazwy zgodne z następującym formatem:
myDsl.diagram
myDsl.myDsl
Domyślny schemat serializacji
Aby utworzyć przykład dla tego tematu, użyto następującej definicji DSL.
Ten język DSL został użyty do utworzenia modelu, który ma następujący wygląd na ekranie.
Ten model został zapisany, a następnie ponownie otwarty w edytorze tekstów XML:
<?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>
Zwróć uwagę na następujące kwestie dotyczące serializowanego modelu:
Każdy węzeł XML ma nazwę, która jest taka sama jak nazwa klasy domeny, z tą różnicą, że początkowa litera jest małą literą. Przykład:
familyTreeModel
iperson
.Właściwości domeny, takie jak Name i BirthYear, są serializowane jako atrybuty w węzłach XML. Ponownie początkowy znak nazwy właściwości jest konwertowany na małe litery.
Każda relacja jest serializowana jako węzeł XML zagnieżdżony wewnątrz końca źródłowej relacji. Węzeł ma taką samą nazwę jak właściwość roli źródłowej, ale z małym znakiem początkowym.
Na przykład w definicji DSL rola o nazwie People jest źródłowa w klasie FamilyTree . W kodzie XML rola People jest reprezentowana z węzłem o nazwie
people
zagnieżdżonym wewnątrz węzłafamilyTreeModel
.Docelowy koniec każdej relacji osadzania jest serializowany jako węzeł zagnieżdżony w ramach relacji. Na przykład
people
węzeł zawiera kilkaperson
węzłów.Docelowy koniec każdej relacji odwołania jest serializowany jako moniker, który koduje odwołanie do elementu docelowego.
Na przykład w węźle
person
może istniećchildren
relacja. Ten węzeł zawiera elementy monikers, takie jak:<personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" />
Omówienie monikers
Monikers są używane do reprezentowania odsyłaczy między różnymi częściami modelu i plików diagramu. Są one również używane w .diagram
pliku do odwoływania się do węzłów w pliku modelu. Istnieją dwie formy moniker:
Identyfikatory monikers cytują identyfikator GUID elementu docelowego. Na przykład:
<personShapeMoniker Id="f79734c0-3da1-4d72-9514-848fa9e75157" />
Kwalifikowane elementy monikers klucza identyfikują element docelowy według wartości wyznaczonej właściwości domeny nazywanej kluczem moniker. Moniker elementu docelowego jest poprzedzony pseudonimem jego elementu nadrzędnego w drzewie osadzania relacji.
Poniższe przykłady pochodzą z dsL, w którym istnieje klasa domeny o nazwie Album, która ma relację osadzania do klasy domeny o nazwie Song:
<albumMoniker title="/My Favorites/Jazz after Teatime" /> <songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" />
Kwalifikowane elementy monikers kluczy są używane, jeśli klasa docelowa ma właściwość domeny, dla której opcja Jest kluczem Moniker jest ustawiona na
true
w zachowaniu serializacji XML. W tym przykładzie ta opcja jest ustawiana dla właściwości domeny o nazwie "Title" w klasach domen "Album" i "Song".
Kwalifikowane moniki kluczy są łatwiejsze do odczytania niż identyfikatory monikers. Jeśli zamierzasz, aby kod XML plików modelu był czytelny dla człowieka, rozważ użycie kwalifikowanych monikerów kluczy. Jednak użytkownik może ustawić więcej niż jeden element, aby miał ten sam klucz moniker. Zduplikowane klucze mogą spowodować, że plik nie zostanie poprawnie załadowany ponownie. W związku z tym, jeśli zdefiniujesz klasę domeny, do której odwołuje się kwalifikowany monikers kluczy, należy rozważyć sposoby uniemożliwienia użytkownikowi zapisywania pliku, który ma zduplikowane elementy monikers.
Aby ustawić klasę domeny do przywołowania przez elementy monikers identyfikatorów
Upewnij się, że właściwość Is Moniker Key jest
false
dla każdej właściwości domeny w klasie i jej klasach bazowych.W Eksploratorze DSL rozwiń węzeł Zachowanie serializacji XML\Dane klasy\<klasa> domeny\Dane elementu.
Sprawdź, czy klucz Moniker jest
false
przeznaczony dla każdej właściwości domeny.Jeśli klasa domeny ma klasę bazową, powtórz procedurę w tej klasie.
Ustaw wartość Serialize Id =
true
dla klasy domeny.Tę właściwość można znaleźć w obszarze Zachowanie serializacji XML.
Aby ustawić klasę domeny do przywołowania przez kwalifikowane elementy monikers kluczy
Ustaw wartość To Moniker Key dla właściwości domeny istniejącej klasy domeny. Typ właściwości musi mieć wartość
string
.W Eksploratorze DSL rozwiń węzeł Xml Serialization Behavior\Class Data\<the domain class>\Element Data, a następnie wybierz właściwość domeny.
W okno Właściwości ustaw wartość Is Moniker Key na
true
.
- lub -
Utwórz nową klasę domeny przy użyciu narzędzia Nazwana klasa domeny.
To narzędzie tworzy nową klasę, która ma właściwość domeny o nazwie Name. Właściwości Is Element Name i Is Moniker Key tej właściwości domeny są inicjowane na
true
.- lub -
Utwórz relację Dziedziczenie z klasy domeny do innej klasy, która ma właściwość klucza moniker.
Unikaj duplikowania Monikers
Jeśli używasz kwalifikowanych monikers kluczy, możliwe, że dwa elementy w modelu użytkownika mogą mieć tę samą wartość we właściwości klucza. Jeśli na przykład rozszerzenie DSL ma klasę Person, która ma właściwość Name, użytkownik może ustawić nazwy dwóch elementów na takie same. Mimo że model można zapisać w pliku, nie zostanie poprawnie załadowany.
Istnieje kilka metod, które pomagają uniknąć tej sytuacji:
Ustaw wartość Is, =
true
nazwa elementu dla właściwości domeny klucza. Wybierz właściwość domeny na diagramie definicji DSL, a następnie ustaw wartość w okno Właściwości.Gdy użytkownik utworzy nowe wystąpienie klasy, ta wartość powoduje automatyczne przypisanie właściwości domeny do innej wartości. Domyślne zachowanie dodaje liczbę na końcu nazwy klasy. Nie uniemożliwia to użytkownikowi zmiany nazwy na duplikat, ale pomaga w przypadku, gdy użytkownik nie ustawi wartości przed zapisaniem modelu.
Włącz walidację dla rozszerzenia DSL. W Eksploratorze DSL wybierz pozycję Editor\Validation i ustaw właściwości Uses... na
true
.Istnieje automatycznie wygenerowana metoda sprawdzania poprawności, która sprawdza niejednoznaczności. Metoda znajduje się w
Load
kategorii walidacji. Dzięki temu użytkownik zostanie ostrzeżony, że ponowne otwarcie pliku może nie być możliwe.Aby uzyskać więcej informacji, zobacz Walidacja w języku specyficznym dla domeny.
Ścieżki i kwalifikatory moniker
Kwalifikowany moniker klucza kończy się kluczem moniker i jest poprzedzony pseudonimem jego elementu nadrzędnego w drzewie osadzania. Jeśli na przykład pseudonim albumu to:
<albumMoniker title="/My Favorites/Jazz after Teatime" />
Następnie jednym z utworów w tym albumie może być:
<songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" />
Jeśli jednak zamiast tego albumy są przywoływały identyfikator, zamiast tego monikers będą wyglądać następująco:
<albumMoniker Id="77472c3a-9bf9-4085-976a-d97a4745237c" />
<songMoniker title="/77472c3a-9bf9-4085-976a-d97a4745237c/Hot tea" />
Zwróć uwagę, że ponieważ identyfikator GUID jest unikatowy, nigdy nie jest poprzedzony pseudonimem elementu nadrzędnego.
Jeśli wiesz, że określona właściwość domeny zawsze będzie miała unikatową wartość w modelu, możesz ustawić właściwość Is Moniker Qualifier na true
wartość dla tej właściwości. Powoduje to, że może być używany jako kwalifikator, bez użycia pseudonimu elementu nadrzędnego. Jeśli na przykład ustawisz zarówno właściwość Is Moniker Qualifier , jak i Is Moniker Key dla właściwości Domain Title klasy Album, nazwa lub identyfikator modelu nie jest używany w elementach monikers dla albumu i jej osadzonych elementów podrzędnych:
<albumMoniker name="Jazz after Teatime" />
<songMoniker title="/Jazz after Teatime/Hot tea" />
Dostosowywanie struktury kodu XML
Aby wprowadzić następujące dostosowania, rozwiń węzeł Zachowanie serializacji XML w Eksploratorze DSL. W obszarze klasy domeny rozwiń węzeł Dane elementu, aby wyświetlić listę właściwości i relacji, które są źródłowe w tej klasie. Wybierz relację i dostosuj jej opcje w okno Właściwości.
Ustaw opcję Pomiń element na wartość true, aby pominąć węzeł roli źródłowej, pozostawiając tylko listę elementów docelowych. Nie należy ustawiać tej opcji, jeśli istnieje więcej niż jedna relacja między klasami źródłowymi i docelowymi.
<familyTreeModel ...> <!-- The following node is omitted by using Omit Element: --> <!-- <people> --> <person name="Henry VIII" .../> <person name="Elizabeth I" .../> <!-- </people> --> </familyTreeModel>
Ustaw opcję Użyj pełnego formularza , aby osadzić węzły docelowe w węzłach reprezentujących wystąpienia relacji. Ta opcja jest ustawiana automatycznie podczas dodawania właściwości domeny do relacji domeny.
<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>
Ustaw element reprezentacji = na właściwość domeny zapisaną jako element zamiast jako wartość atrybutu.
<person name="Elizabeth I" birthYear="1533"> <deathYear>1603</deathYear> </person>
Aby zmienić kolejność serializacji atrybutów i relacji, kliknij prawym przyciskiem myszy element w obszarze Dane elementu i użyj poleceń menu Przenieś w górę lub Przenieś w dół .
Dostosowywanie główne przy użyciu kodu programu
Części lub wszystkie algorytmy serializacji można zastąpić.
Zalecamy zapoznanie się z kodem w kodzie Dsl\Generated Code\Serializer.cs i SerializationHelper.cs.
Aby dostosować serializacji określonej klasy
Set Is Custom in the node for that class under Xml Serialization Behavior (Ustawienie jest niestandardowe w węźle dla tej klasy w obszarze Zachowanie serializacji XML).
Przekształć wszystkie szablony, skompiluj rozwiązanie i zbadaj wynikowe błędy kompilacji. Komentarze w pobliżu każdego błędu wyjaśniają, jaki kod należy podać.
Aby zapewnić własną serializacji dla całego modelu
- Zastąpij metody w pliku Dsl\GeneratedCode\SerializationHelper.cs
Uwaga
Począwszy od programu Visual Studio 2022 w wersji 17.13, domyślna implementacja serializacji nie obsługuje już serializacji ani deserializacji niestandardowych typów danych przy użyciu klasy BinaryFormatter ze względu na zagrożenia bezpieczeństwa w programie BinaryFormatter.
Jeśli używasz niestandardowego typu danych dla dowolnych właściwości domeny, musisz zastąpić metody serializacji w SerializationHelper
klasie lub zaimplementować TypeConverter
możliwość konwertowania każdego niestandardowego typu danych na i z ciągu.
Chociaż nie zalecamy używania ze BinaryFormatter
względów bezpieczeństwa, jeśli musisz zachować zgodność wsteczną ze starszymi modelami, które używały BinaryFormatter
serializacji, można zaimplementować TypeConverter
deserializację danych binarnych. Poniższy fragment kodu służy jako szablon do implementowania tej zgodności:
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
{
// ...
}
Opcje w zachowaniu serializacji xml
W Eksploratorze DSL węzeł Zachowanie serializacji XML zawiera węzeł podrzędny dla każdej klasy domeny, relacji, kształtu, łącznika i klasy diagramu. W każdym z tych węzłów znajduje się lista właściwości i relacji źródłowych w tym elemecie. Relacje są reprezentowane zarówno we własnym zakresie, jak i w ramach klas źródłowych.
Poniższa tabela zawiera podsumowanie opcji, które można ustawić w tej sekcji definicji DSL. W każdym przypadku wybierz element w Eksploratorze DSL i ustaw opcje w okno Właściwości.
Dane klasy XML
Te elementy znajdują się w Eksploratorze DSL w obszarze Zachowanie serializacji XML\Dane klasy.
Właściwości | opis |
---|---|
Ma niestandardowy schemat elementu | Jeśli wartość True, wskazuje, że klasa domeny ma niestandardowy schemat elementu |
Jest niestandardowy | Ustaw wartość True , jeśli chcesz napisać własny kod serializacji i deserializacji dla tej klasy domeny. Skompiluj rozwiązanie i zbadaj błędy, aby odnaleźć szczegółowe instrukcje. |
Klasa domeny | Klasa domeny, do której ma zastosowanie ten węzeł danych klasy. Tylko do odczytu. |
Nazwa elementu | Nazwa węzła XML dla elementów tej klasy. Wartość domyślna to niższa wersja nazwy klasy domeny. |
Nazwa atrybutu Moniker | Nazwa atrybutu używanego w elementach moniker do przechowywania odwołania. Jeśli jest pusta, używana jest nazwa właściwości lub identyfikatora klucza. W tym przykładzie jest to "name": <personMoniker name="/Mike Nash"/> |
Nazwa elementu Moniker | Nazwa elementu xml używanego dla elementów monikers odwołujących się do elementów tej klasy. Wartość domyślna to mała wersja nazwy klasy z sufiksem "Moniker". Na przykład personMoniker . |
Nazwa typu moniker | Nazwa typu xsd wygenerowanego dla elementów tej klasy monikers. XSD znajduje się w pliku Dsl\Generated Code\*Schema.xsd |
Serializowanie identyfikatora | Jeśli wartość True, identyfikator GUID elementu jest uwzględniony w pliku. Wartość musi być ustawiona na Wartość True, jeśli nie ma właściwości oznaczonej jako Klucz Moniker, a rozszerzenie DSL definiuje relacje odwołania do tej klasy. |
Nazwa typu | Nazwa typu xml wygenerowanego w xsd z wyznaczonej klasy domeny. |
Uwagi | Notatki nieformalne skojarzone z tym elementem |
Dane właściwości XML
Węzły właściwości XML znajdują się w węzłach klasy.
Właściwości | opis |
---|---|
Właściwość domeny | Właściwość, do której mają zastosowanie dane konfiguracji serializacji XML. Tylko do odczytu. |
Jest kluczem Moniker | Jeśli wartość jest ustawiona na True, właściwość jest używana jako klucz do tworzenia obiektów monikers odwołujących się do wystąpień tej klasy domeny. |
Czy kwalifikator moniker | Jeśli wartość jest ustawiona na True, właściwość jest używana do tworzenia kwalifikatora w monikers. Jeśli wartość false i jeśli parametr SerializeId nie jest spełniony w tej klasie domeny, monikers są kwalifikowane przez pseudonim elementu nadrzędnego w drzewie osadzania. |
Reprezentacja | Jeśli wartość jest ustawiona na Atrybut, właściwość jest serializowana jako atrybut XML; jeśli wartość jest ustawiona na Element, jest serializowany jako element; jeśli wartość jest ustawiona na Ignoruj, to nie jest serializowany. |
Nazwa xml | Nazwa używana dla atrybutu xml lub elementu reprezentującego właściwość . Domyślnie wartość jest niższą wersją nazwy właściwości domeny. |
Uwagi | Notatki nieformalne skojarzone z tym elementem |
Dane roli XML
Węzły danych roli znajdują się w węzłach klasy źródłowej.
Właściwości | opis |
---|---|
Ma niestandardowy moniker | Ustaw wartość true, jeśli chcesz podać własny kod do generowania i rozpoznawania jednostek monikerów przechodzących przez tę relację. Aby uzyskać szczegółowe instrukcje, skompiluj rozwiązanie, a następnie kliknij dwukrotnie komunikaty o błędach. |
Relacja domeny | Określa relację, do której mają zastosowanie te opcje. Tylko do odczytu. |
Pomiń element | Jeśli to prawda, węzeł XML odpowiadający roli źródłowej zostanie pominięty ze schematu. Jeśli istnieje więcej niż jedna relacja między klasami źródłowymi i docelowymi, ten węzeł roli rozróżnia łącza należące do dwóch relacji. W związku z tym zalecamy, aby nie ustawić tej opcji w tym przypadku. |
Nazwa elementu roli | Określa nazwę elementu XML, który pochodzi z roli źródłowej. Wartość domyślna to nazwa właściwości roli. |
Korzystanie z pełnego formularza | Jeśli wartość true, każdy element docelowy lub moniker jest ujęty w węźle XML reprezentującym relację. Ta wartość powinna być ustawiona na wartość true, jeśli relacja ma własne właściwości domeny. |