CodeGym /Kurslar /C# SELF /XML serializasiyasının tənzimlənməsi

XML serializasiyasının tənzimlənməsi

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Artıq bilirsiniz ki, .NET default olaraq public sahələrə və propertielərə əsaslanaraq obyektləri XML-ə serialize və deserialize edə bilir. Amma gözəl, xarici proqramlara/standartlara uyğun XML yaratmaq, ya da XML-ə bəzi daxili detalların daxil olmamasını istəyirsinizsə, incə tənzimləmə lazımdır.

C#-da bunun üçün serializasiya atributları var — sinifləri, propertieləri və ya sahələri işarələmək üçün xüsusi "tag"lar. Bu atributlar sayəsində hər şeyi idarə edə bilirsiniz: hansı sahələr XML-ə düşəcək, hansılar ignore ediləcək, elementin adı nə olacaq, atribut olaraq yazılacaq, mürəkkəb struktur olacaq, hətta elementlərin sırası nə olacaq!

Default serializasiya avtomatik form doldurma kimidir: ad-familiya-ata adı öz yerlərində, qalanı necə gəldi. Atributlarla siz super-kanselyar kimi qərar verirsiniz: hansı sətri haraya yazmaq, nəyi ötürmək, nəyi qırmızıya çəkmək, nəyi sirr bölməsinə keçirmək.

Obyektin və XML-in uyğunlaşdırılması

Sinif/Property Atribut XML-də nəticə
[XmlRoot("Persons")]
Class UserList
<Persons>...</Persons>
List<User> Users
[XmlElement("Person")]
<Person>...</Person>
int Id
[XmlAttribute("id")]
id="..." (atribut)
string Name
[XmlElement("FullName")]
<FullName>...</FullName>
string[] Emails
[XmlArray("EMails")][XmlArrayItem("Email")]
<EMails><Email>...</Email></EMails>
DateTime RegisteredAt
[XmlIgnore] (bax RegisteredAtString) -
string RegisteredAtString
[XmlAttribute("registered")]
registered="..."
Address[] Addresses
[XmlArray("UserAddresses")][XmlArrayItem("Address")]
<UserAddresses>...</UserAddresses>

2. XML serializasiyasının əsas atributlarına baxış

Gəlin .NET istifadəçilərinin nəslər boyu siniflərini bəzədiyi ən populyar atributlara baxaq!

Atribut [XmlElement] — Elementin adı

XML-də elementin adını dəyişir və ya property/field-i XML-element kimi işarələyir.

public class Person
{
    [XmlElement("FullName")]
    public string Name { get; set; }
}

XML:

<Person>
  <FullName>Vasiliy Petrov</FullName>
</Person>

Əgər atribut göstərməsəniz — default olaraq elementin adı property/field-in adı ilə eyni olacaq.

Atribut [XmlAttribute] — XML atribut kimi serializasiya

Property/field-i element əvəzinə XML-atribut kimi serialize etməyə imkan verir.

public class Person
{
    [XmlAttribute("id")]
    public int Id { get; set; }
}

XML:

<Person id="123"></Person>

Real XML-API-lərdə adlar, tarixlər, flag-lər üçün atributlar tez-tez istifadə olunur.

Atribut [XmlIgnore] — Field/property-ni keçirmək

Paranoid üçün arzu: property-ni tamamilə serializasiya və deserializasiyadan çıxarmaq! Bu atributla işarələnmiş hər şey final XML-ə düşməyəcək.

public class Person
{
    [XmlIgnore]
    public string InternalNote { get; set; }
}

XML: (InternalNote burada yoxdur və olmayacaq)

Atributlar [XmlArray][XmlArrayItem] — kolleksiyalara nəzarət

Array və kolleksiyalar üçün xüsusi atributlar. [XmlArray] xarici wrapper-in adını verir, [XmlArrayItem] isə ayrı elementin adını təyin edir.

public class Person
{
    [XmlArray("Phones")]
    [XmlArrayItem("Phone")]
    public string[] PhoneNumbers { get; set; }
}

XML:

<Person>
  <Phones>
    <Phone>+12951234567</Phone>
    <Phone>+12876543210</Phone>
  </Phones>
</Person>

Atribut [XmlRoot] — Root elementin adı

Sinifi işarələyib XML-də root elementin adını dəyişməyə imkan verir.

[XmlRoot("User")]
public class Person
{
    public string Name { get; set; }
}

XML:

<User>
  <Name>Anna</Name>
</User>

Atribut [XmlText] — Elementin mətn məzmunu kimi serializasiya

Bəzən (və ya spesifikasiya tələb edirsə) property-nin dəyəri elementin içində sadəcə mətn kimi olmalıdır, nested element və ya atribut kimi yox.

public class Note
{
    [XmlText]
    public string Content { get; set; }
}

XML:

<Note>Pozvoni babushke!</Note>

Atributlar [XmlNamespaceDeclarations], [XmlElement(Type = ...)]

Daha avanqard ssenarilər (məsələn, namespace-lərlə serializasiya, inheritance dəstəyi və s.) üçün spesifik atributlar da var. Tam siyahı üçün mütləq rəsmi sənədlərə baxın.

3. Praktika: real nümunədə serializasiyanı yaxşılaşdırmaq

Gəlin addım-addım tədris tətbiqimizi "XML-serializasiya premium" səviyyəsinə gətirək ki, ən ciddi XML-inspektoru da razı qalsın.

Atributlar olmadan baza sinif

Tutaq ki, istifadəçi üçün belə bir sinifimiz var:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string[] Emails { get; set; }
    public DateTime RegisteredAt { get; set; }
    public string Password { get; set; }
}

Default serializasiya təxminən belə XML verəcək (tarixi öz formatında yazacaq):

<User>
  <Id>42</Id>
  <Name>Ivan Ivanov</Name>
  <Emails>
    <string>user@mail.com</string>
    <string>admin@site.org</string>
  </Emails>
  <RegisteredAt>2024-07-01T00:00:00</RegisteredAt>
  <Password>qwerty</Password>
</User>

Nə problemdir:

  • Şifrə ümumiyyətlə serializasiya olunmasın.
  • Tarixi atribut olaraq və insan üçün oxunaqlı formatda istəyirik.
  • Emails-ləri gözəl formada istəyirik.
  • Root elementi <Person> olsun istəyirik.

Atributlarla tənzimləmə əlavə edirik

[XmlRoot("Person")]
public class User
{
    [XmlAttribute("id")]
    public int Id { get; set; }

    [XmlElement("FullName")]
    public string Name { get; set; }

    [XmlArray("EMails")]
    [XmlArrayItem("Email")]
    public string[] Emails { get; set; }

    [XmlAttribute("registered")]
    public string RegisteredAtString
    {
        get => RegisteredAt.ToString("yyyy-MM-dd");
        set => RegisteredAt = DateTime.Parse(value);
    }

    [XmlIgnore]
    public string Password { get; set; }

    [XmlIgnore]
    public DateTime RegisteredAt { get; set; }
}

İncə məqamların açıqlaması:

  • Tarixi atribut kimi serializasiya etmək üçün [XmlAttribute("registered")] istifadə edirik.
  • Birbaşa DateTime-ı deyil, onun string təmsilini serializasiya etmək üçün ayrıca RegisteredAtString property əlavə edirik, real sahəni isə [XmlIgnore] ilə gizlədirik.
  • Şifrəni [XmlIgnore] ilə gizlədirik.
  • Email massivini belə tənzimləyirik: xarici tag <EMails>, hər email üçün isə <Email>.

Nəticə:

<Person id="42" registered="2024-07-01">
  <FullName>Ivan Ivanov</FullName>
  <EMails>
    <Email>user@mail.com</Email>
    <Email>admin@site.org</Email>
  </EMails>
</Person>

4. Nested obyektlərlə işləmək

XML nested obyektlər olduqda ən yaxşısını göstərir (məsələn, istifadəçi və onun ünvanları).

public class Address
{
    [XmlAttribute]
    public string City { get; set; }

    [XmlText]
    public string Details { get; set; }
}

public class User
{
    // ...digər propertielər, yuxarıya baxın...

    public Address[] Addresses { get; set; }
}

Və ünvan massivinə tənzimləmə əlavə edək:

[XmlArray("UserAddresses")]
[XmlArrayItem("Address")]
public Address[] Addresses { get; set; }

Onda XML belə olacaq:

<Person id="42" registered="2024-07-01">
  <FullName>Ivan Ivanov</FullName>
  <EMails>
    <Email>user@mail.com</Email>
  </EMails>
  <UserAddresses>
    <Address City="Neon city">ul. Zamkovaya, d.1</Address>
    <Address City="North Cave">ul. Kraynaya d.12</Address>
  </UserAddresses>
</Person>

Göründüyü kimi hər <Address>-in City atributu var, ünvanın özü isə elementin içində mətndir.

5. Tez-tez rast gəlinən səhvlər və nüanslar

Əgər mürəkkəb bir obyekti serialize edirsinizsə və gözlədiyiniz dəyişiklikləri XML-də görmürsünüzsə — çox güman ki, atributu düzgün göstərməmisiniz. Bəzən propertielər/sahələr markalanmamış qalır, onda .NET default davranışı seçir.

Bir başqa tələyə diqqət: kolleksiya adı. Əgər kolleksiya (məsələn, string massivi) həm [XmlArray], həm [XmlArrayItem] ilə işarələnməyibsə, elementlər string tagı ilə yazılacaq (ilk nümunədə görüldüyü kimi). Bunun olmaması üçün həmişə tag adlarını açıq şəkildə verin.

"Getter-only" tipli propertielərlə ehtiyatlı olun — onlar default olaraq deserializasiya olunmur. Public set qoymağa çalışın.

Bəzi tiplər (məsələn, dictionary-lər və ya interface-lər) standart XmlSerializer ilə serialize olunmur və ya əlavə işlənmə tələb edir.

2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
XmlArray və XmlArrayItem istifadə edərək kolleksiyanın seriyalaşdırılması
XmlArray və XmlArrayItem istifadə edərək kolleksiyanın seriyalaşdırılması
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION