Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.
Pojęcie serializacji oraz jej zastosowanie mam nadzieje, że jest Wam znane chociażby z poprzedniego artykułu Daniela. Dzisiaj postaram się przedstawić serializacje za pomocą formatera XML.
.NET Framework zawiera kilka bibliotek do odczytu i zapisu plików XML. My zajmiemy się tą z przestrzeni nazw System.Xml.Serialization. Za pomocą serializacji XML możemy zapisać niemal każdy obiekt do pliku tekstowego a następnie odczytać go w kilku linijkach kodu. Serializacji XML można użyć do przesyłania stanów obiektu pomiędzy komputerami za pomocą usług web-owych nawet jeśli komputer zdalny nie wykorzystuje .NET Framework.
Dlaczego używać serializacji XML?
Większa interoperacyjność - XML bazuję na standartowym pliku tekstowym. Wszystkie nowoczesne środowiska udostępniają biblioteki do pracy na plikach XML. Stąd obiekt który został zserializowany można wykorzystywać do aplikacji pisanych na różne systemy operacyjne i w różnych środowiskach.
Przyjazne zarządzanie – zserializowane obiekty możemy przeglądać i edytować w dowolnym edytorze tekstu, chociażby w zwykłym notatniku. Oczywiście jeśli mamy do tego uprawnienia. Może to być przydatne do dostosowywania aplikacji, rozwiązywania problemów, oraz rozwój nowych aplikacji, które współdziałają z istniejącymi już programami.
Lepsza późniejsza kompatybilność – obiekty po serializacji mają swój własny opis i są łatwo przetwarzalne. Więc kiedy przyjdzie czas zastąpienia aplikacji na nowszą wersję proces przetwarzania zserializowanych obiektów zajmie nam mniej czasu.
Ograniczeniem serializacji XML jest to, że możemy serializować tylko publiczne dane oraz tylko obiekty.
Jak użyć serializacji na obiekcie
Kroki serializacji obiektu do pliku XML są następujące:
- Tworzenie strumienia TextWriter lub XmlWriter do przechowywania danych wyjściowych
- Tworzenie obiektu XmlSerializer do przekazania obiektu do serializacji
- Na koniec należy wywołać metode serialize
Przykład:
1: // Create file to save the data
2: FileStream fs = new FileStream("SerializedDate.XML", FileMode.Create);
3: // Create an XmlSerializer object to perform the serialization
4: XmlSerializer xs = new XmlSerializer(typeof(DateTime));
5: // Use the XmlSerializer object to serialize the data to the file
6: xs.Serialize(fs, System.DateTime.Now);
7: // Close the file
8: fs.Close();
Kod ten zwróci nam następujący plik z danymi:
<?xml version="1.0" ?>
<dateTime>2008-06-05T16:28:11.0533408-05:00</dateTime>
Deserializacja obiektu
Kroki deserializacji obiektu są następujące:
- Tworzenie strumienia TextWriter lub XmlWriter do odczytania zserializowanych danych wejściowych
- Tworzenie obiektu XmlSerializer do przekazania obiektu do deserializacji
- Na koniec wywołać należy metodę deserialize obiektu i zrzutować na odpowiedni typ
Przykład:
1: // Open file from which to read the data
2: FileStream fs = new FileStream("SerializedDate.XML", FileMode.Open);
3: // Create an XmlSerializer object to perform the deserialization
4: XmlSerializer xs = new XmlSerializer(typeof(DateTime));
5: // Use the XmlSerializer object to deserialize the data from the file
6: DateTime previousTime = (DateTime)xs.Deserialize(fs);
7: // Close the file
8: fs.Close();
9: // Display the deserialized time
10: Console.WriteLine("Day: " + previousTime.DayOfWeek + ", Time: "
11: + previousTime.TimeOfDay.ToString());
Jak stworzyć klasy które można serializować do XML?
Aby utworzyć klasę która może być serializowana do postaci XML musimy pamiętać o trzech podstawowych rzeczach:
Po pierwsze klasa musi być publiczna. Po drugie wszystkie składowe klasy które mają zostać poddane serializacji należy ustawić również na publiczne. Po trzecie dodać do klasy konstruktor domyślny.
W przeciwieństwie do standartowej serializacji w tych klasach nie musimy ustawiać atrybutów do pól prywatnych itp. żeby nie były serializowane…jest to robione automatycznie, tzn. że pola chronione i prywatne są pomijane w procesie serializacji.
Jak kontrolować serializacje?
Jeśli klasa spełnia warunki serializacji i nie będziemy używać żadnych dodatkowych atrybutów proces serializacji uruchomi swoje domyślne ustawienia. Nazwy elementów XML są oparte o nazwę klasy i jej składowe. Spójrzmy na przykład klasy oraz jej postać XML po serializacji:
1: public class ShoppingCartItem
2: {
3: public Int32 productId;
4: public decimal price;
5: public Int32 quantity;
6: public decimal total;
7: public ShoppingCartItem()
8: {
9: }
10: }
<?xml version="1.0" ?>
<ShoppingCartItem>
<productId>100</productId>
<price>10.25</price>
<total>20.50</total>
<quantity>2</quantity>
</ShoppingCartItem>
Jeśli chcemy stworzyć inny schemat XML musimy skorzystać z atrybutów. Training Kit wymienia ich bodajże dziesięć ;) Ja je tylko na koniec wymienię bo to jest cała ładna tabelka którą warto znać gdyż pojawiają się pytania w przykładowych pytaniach na koniec rozdziału. XmlArrayItem, XmlAttribute, XmlChoiceIdentifier, XmlElement, XmlEnum, XmlIgnore, XmlInclude, XmlRoot, XmlText, XmlType.
Mam nadzieje, że mi wybaczycie ale moim celem nie jest tłumaczenie książki ;) Wiele z tych atrybutów jest zrozumiała intuicyjnie np. XmlIgnore jest odpowiednikiem NonSerialized itp. itd.
Żeby już nie przeciągać artykułu który i tak zrobił znowu się długi wrzucam przykład kodu oraz plik xml który by się stworzył:
1: [XmlRoot ("CartItem")]
2: public class ShoppingCartItem
3: {
4: [XmlAttribute] public Int32 productId;
5: public decimal price;
6: public Int32 quantity;
7: [XmlIgnore] public decimal total;
8: public ShoppingCartItem()
9: {
10: }
11: }
<?xml version="1.0" ?>
<CartItem productId="100">
<price>10.25</price>
<quantity>2</quantity>
</CartItem>
Dzięki za przeczytanie artykułu. Następny artykuł będzie o niestandardowej serializacji. Mój natomiast o pracy z rysunkami itd. Szykuje się długi wpis także następnym razem zapraszam z kawą ;)
Kolejny artykuł z serii to 70-536: Custom Serialization