wtorek, 27 października 2015

XmlSerializer - Cz1. Serializacja, deserializacja ( + Extension Methods)

W tym poście przedstawię proste sposoby na serializację i deserializację danych. Przy okazji przedstawię również pewnie już znane extension methods. Nie będę się tu rozwodził na składnią samej aplikacji więc wykonamy to po prostu w zwykłej Consoli. Wykonajmy więc Listę osób, które do których przypisany będzie zestaw maili i loginów z których korzystają te osoby. Stwórzmy zatem aplikację konsolową:



W tym celu wykonamy prostą klasę Person, która będzie częścią listy People. Każda osoba posiada przypisany zestaw linków w polu List<Email>.

public class Person
{
    public int PersonId { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }

    public List<Email> Emails { get; set; }
}

Natomiast prosta klasa Email wygląda następująco:

public class Email
{
    public string EmailValue { get; set; }

    public string UserName { get; set; }
}

Teraz Przejdźmy do repozytorium:

interface IRepository
{
    void AddPerson(Person person);

    void SaveToXml();

    void LoadFromXml();
}

I sama klasa:

class PopleRepository : IRepository
{
    private string _assemblyDirectory;

    private static int _peopleersonId;

    public List<Person> PeopleList { get; set; }

    private int SetNewId()
    {
        return ++_peopleersonId;
    }

    public void AddPerson(Person person)
    {
        if (PeopleList == null)
        {
            PeopleList = new List<Person>();
        }
        person.PersonId = SetNewId();
        PeopleList.Add(person);
    }
    //....Kolejne metody IRepository
}

No własnie.. i tu przechodzimy do sedna. Tak będą wyglądały Metody zapisu i odczytu z xml'a:

public void SaveToXml()
{
    var xSerializer = new XmlSerializer(typeof(List<Person>));

    using (var writer = new StreamWriter(_assemblyDirectory))
    {
        xSerializer.Serialize(writer, PeopleList);
    }
}

public void LoadFromXml()
{
    var tmpXmlSerializer = new XmlSerializer(typeof(List<Person>));

    var reader = new StreamReader(_assemblyDirectory);

    object obj = tmpXmlSerializer.Deserialize(reader);

    PeopleList = obj as List<Person>;
}

Przy zapisie musimy stworzyć typ XmlSerializer i określić jakiego typu wartości będą w nim umieszczone. SteramWriter podobnie jak StreamReader tworzy specjalną instancję ścieżki zapisu/odczytu wymaganą przez XmlSerializer. Pole _assemblyDirectory określa ścieżkę do pliku.

W celu nadania losowych wartości polecam odwiedzić stronę Faker.net. Znajdują się tam biblioteki do nadawania losowych wartości teleadresowych. Wystarczy uruchomić Package Manager Console i tam wpisać następującą komendę:

PM> Install-Package Faker.Net

I już możemy dodawać wartości z bibliotek w następujący sposób:

new Person
{
    Name = Faker.Name.First(),
    Surname = Faker.Name.Last(),
};

Biblioteka o niewymownej nazwie sama wygeneruje nam losowo imiona i nazwiska stworzonych osób.

Stwórzmy na szybko jeszcze jakąś metodę w klasie program generującą poszczególne osoby w repozytorium:

/// <summary>
/// Klasa Generująca repozytorium osób
/// </summary>
/// <param name="noOfPeople">Ilośc osób w repozytorium</param>
/// <param name="path">Ścieżka pliku do zapisu</param>
/// <returns></returns>
public static PeopleRepository GenerateRepository(int noOfPeople, string path = @"d:/testPath.text")
{
    var genTmpRepo = new PeopleRepository();

    var rndNoOfEmails = new Random();

    for (int i = 0; i < noOfPeople; i++)
    {
        genTmpRepo.AddPerson(
            new Person
            {
                Name = Faker.Name.First(),
                Surname = Faker.Name.Last(),
            });
    }

    foreach (var per in genTmpRepo.PeopleList)
    {
        int tmpVal = rndNoOfEmails.Next(1, 5);
        for (int i = 0; i < tmpVal; i++)
        {
            per.Emails.Add(new Email
                {
                    EmailValue = Faker.Internet.Email(),
                    Username = Faker.Internet.UserName()
                });
        }
    }
    return genTmpRepo;
}

Przy okazji wykonajmy jeszcze metodę rozszerzającą SimpleRepositoryExt, aby sprawdzić co zostało wygenerowane:

public static class SimpleRepositoryExt
{
    public static void ShowValues(this PeopleRepository peopleRepository)
    {
        foreach (var per in peopleRepository.PeopleList)
        {
            Console.WriteLine("Id : {0} Name : {1}, Surname : {2}", per.PersonId, per.Name, per.Surname);
            Console.WriteLine("----------------------------");
            foreach (var em in per.Emails)
            {
                Console.WriteLine("Login : {0}\n Email : {1}", em.Username, em.EmailValue);
            }
            Console.WriteLine("\n\n\n");
        }
    }
}

Przejdźmy teraz do klasy Program i wykorzystajmy stworzone metody do zapisania wartości do pliku txt. Jak widać encji tmpPeopleRep mamy dostępne własciwości, metody klasy oraz metody rozszerzające:

static void Main(string[] args)
{
    PeopleRepository tmpPeopleRep = GenerateRepository(3);
    if (tmpPeopleRep == null)
    {
        tmpPeopleRep = new PeopleRepository();
    }
    tmpPeopleRep.SaveToXml();
    tmpPeopleRep.ShowValues();
}

Metoda rozszerzająca ShowValues po odpaleniu kompilatora wyświetla następującą treść: 


Zerknijmy do treści zawartej w pliku XML:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfPeron xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Person>
    <PersonId>1</PersonId>
    <Name>Zelma</Name>
    <Surname>Price</Surname>
    <Emails>
      <Email>
        <EmailValue>stephen@braun.ca</EmailValue>
        <Username>cecil.cruickshank</Username>
      </Email>
    </Emails>
  </Person>
  <Person>
    <PersonId>2</PersonId>
    <Name>Rowena</Name>
    <Surname>Morissette</Surname>
    <Emails>
      <Email>
        <EmailValue>jane_armstrong@medhurstbatz.name</EmailValue>
        <Username>blair</Username>
      </Email>
      <Email>
        <EmailValue>alvina_harber@nienow.biz</EmailValue>
        <Username>liza</Username>
      </Email>
      <Email>
        <EmailValue>quinten@schummokuneva.biz</EmailValue>
        <Username>harley_marks</Username>
      </Email>
      <Email>
        <EmailValue>burley.koelpin@oconner.co.uk</EmailValue>
        <Username>benedict</Username>
      </Email>
    </Emails>
  </Person>
  <Person>
    <PersonId>3</PersonId>
    <Name>Asha</Name>
    <Surname>Sipes</Surname>
    <Emails>
      <Email>
        <EmailValue>margie_ratke@steuber.uk</EmailValue>
        <Username>marge</Username>
      </Email>
      <Email>
        <EmailValue>tanya.runolfsson@baumbach.info</EmailValue>
        <Username>litzy.stamm</Username>
      </Email>
    </Emails>
  </Person>
</ArrayOfPerson>

Jak widać wartości są przekonwertowane do szybkiego odczytu przez aplikacje również użytkownik może względnie przejrzeć zawartość. Odczytajmy teraz zapisane wartości.

static void Main(string[] args)
{
    PeopleRepository tmpPeopleRep = new PeopleRepository();
    tmpPeopleRep.LoadFromXml();
    tmpPeopleRep.ShowValues();
}

Wartości zostaną wczytane do listy i wyświetlone. To tyle w części pierwszej. W części drugiej opiszę trochę więcej o prawidłowej składni klas do obsługi zapisu i odczytu danych z XML


Brak komentarzy:

Prześlij komentarz