Udostępnij za pośrednictwem


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

  1. Otwórz definicję DSL. W Eksploratorze DSL kliknij węzeł Edytor.

  2. W okno Właściwości edytuj właściwość FileExtension. Nie dołączaj początkowego . rozszerzenia nazwy pliku.

  3. 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.

Diagram definicji DSL — model drzewa rodzinnego

Ten język DSL został użyty do utworzenia modelu, który ma następujący wygląd na ekranie.

Diagram drzewa rodzinnego, przybornik i eksplorator

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 i person.

  • 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ła familyTreeModel .

  • Docelowy koniec każdej relacji osadzania jest serializowany jako węzeł zagnieżdżony w ramach relacji. Na przykład people węzeł zawiera kilka person 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

  1. 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.

    1. W Eksploratorze DSL rozwiń węzeł Zachowanie serializacji XML\Dane klasy\<klasa> domeny\Dane elementu.

    2. Sprawdź, czy klucz Moniker jest false przeznaczony dla każdej właściwości domeny.

    3. Jeśli klasa domeny ma klasę bazową, powtórz procedurę w tej klasie.

  2. 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.

    1. W Eksploratorze DSL rozwiń węzeł Xml Serialization Behavior\Class Data\<the domain class>\Element Data, a następnie wybierz właściwość domeny.

    2. 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

  1. 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).

  2. 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

  1. 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.