• Nem Talált Eredményt

1. A webszolgáltatások

1.4. XML-szerializáció

1.4. XML-szerializáció

Ha jól figyeltünk, felismerhetjük, miről is van szó a SOAP kapcsán. A függvény paramétereit ugyanúgy szerializálni kell a meghíváshoz, mint ahogy a függvény visszatérési értékét is. Sajnos a http protokoll nem támogatja a bináris adatforgalmat, mivel a http protokoll igazából nem erre lett kitalálva.

A szerializáció itt nem bináris, hanem XML-szerializáció. A problémái hasonlóak, mint a 9.1. fejezet kapcsán említettek. Az ott ismertetett módszerek (Serializable, Optional, NonSerialized attribútumok, OnDeserialization metódus) az XML-szerializáció kapcsán nem alkalmazhatóak, illetve hasztalanok. Ezek mind a bináris szerializációs és deszerializációs folyamat sajátosságai.

Az XML-szerializáció az alábbi szabályokkal írható le:

• csak a publikus mezők és propertyk értékeivel foglalkozik,

• nem tartalmaz típusinformációkat,

• amely osztályt szerializálni szeretnénk, abban lenni kell alapértelmezett (paraméter nélküli) konstruktornak,

• a publikus propertyknek írható és olvasható műveletekkel is kell rendelkeznie, a csak olvasható propertyk értéke nem kerül szerializálásra.

1.4.1. XML-szerializáció tesztelése

using System.Xml.Serialization;

using System.Xml;

FileStream file = new FileStream(@"c:\teszt.xml", FileMode.Create);

XmlSerializer xs = new XmlSerializer ( typeof ( int ) );

XmlTextWriter xmlTextWriter = new XmlTextWriter ( file, Encoding.UTF8 );

//

int a = 12;

xs.Serialize ( xmlTextWriter, a );

file.Close();

Az eredményül kapott XML fájl az alábbit fogja tartalmazni:

<?xml version="1.0" encoding="utf-8"?>

<int>12</int>

A bináris szerializáció kapcsán is kipróbált városok, személyek, házaspárok alkotta lista szerializácója azonban nem fog sikerülni egy komoly probléma miatt: az XML-szerializáció nem támogatja a körkörös hivatkozású adatok szerializációját! Ha még emlékszünk rá, a 9.6. ábrán bemutatott kapcsolatrendszer szerint a házastársak kölcsönösen tartalmazták egymás referenciáit. Ezen példán keresztül mutattuk be, hogy a bináris szerializációnak többek között ilyen jellegű kapcsolatrendszer kezelését is meg kell oldania. Nos, az XML-szerializációnak is meg kellene – de nem tudja. Ez többek között az XML dokumentum képességeire, illetve a SOAP nem alapos kidolgozottságára vezethető vissza. Ezért az eredeti példa (Lajos felesége Gizi, Gizi férje Lajos) XML-szerializációja esetén (egy elég szerencsétlenül semmitmondó) kivétel jelentkezik. A View detail...

linkre kattintva deríthető csak fel a tényleges hibaok: A circular reference was detected while serializing an object of type szemely körkörös hivatkozás volt az adatokban.

10.6. ábra. Az keletkezett kivétel

10.7. ábra. A kivétel részletező oka

Ezért megszüntetjük a körkörös hivatkozást az által, hogy Lajos esetén bejelöljük Gizit feleségként, de Gizinél nem adjuk meg Lajost férjként. Ne felejtsük el a varos és szemely osztályokat paraméter nélküli (alapértelmezett) konstruktorokkal bővíteni!

Eredménye az alábbi XML fájl lesz. Ha alaposabban elgondolkodunk ennek adattartalmán, világossá válik egy újabb probléma: a Lajos házastársa Gizi egy komplex adatstruktúra, mely leírja Gizi személyes adatait, születési helyét mint várost, de semmi sem utal arra, hogy ez az adattartalom igazából ugyanaz, mint a később (is) Gizi névvel leírt személy adatai. Tehát míg eredetileg a memóriában volt 3 személy, 2 város példány, addig az xml szerializációt helyreállító kód 4 személy és 4 város példányt fog a memóriába „kicsomagolni”, mivel ő mit sem tud arról, hogy a sok „Eger” város igazából ugyanazon példány.

<?xml version="1.0" encoding="utf-8"?>

<ArrayOfSzemely

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<szemely>

<nev>Lajos</nev>

<szul_ev>1970</szul_ev>

<ferfi_e>true</ferfi_e>

<szuletett>

<nev>Eger</nev>

<orszagKod>HU</orszagKod>

</szuletett>

<hazastarsa>

<nev>Gizi</nev>

<szul_ev>1974</szul_ev>

<ferfi_e>false</ferfi_e>

<szuletett>

<nev>Debrecen</nev>

<orszagKod>HU</orszagKod>

</szuletett>

</hazastarsa>

</szemely>

<szemely>

<nev>Gizi</nev>

<szul_ev>1974</szul_ev>

<ferfi_e>false</ferfi_e>

<szuletett>

<nev>Debrecen</nev>

<orszagKod>HU</orszagKod>

</szuletett>

<orszagKod>HU</orszagKod>

</szuletett>

</szemely>

</ArrayOfSzemely>

1.4.2. XML-deszerializáció tesztelése

A deszerializáció a fenti problémáktól eltekintve a forráskódban egyszerűen felírható.

FileStream file = new FileStream(@"c:\teszt2.xml", FileMode.Open);

XmlSerializer xs = new XmlSerializer(typeof(List<szemely>));

List<szemely> l = (List<szemely>)xs.Deserialize(file);

file.Close();

1.4.3. ISerialization

Az XML-szerializácó egyértelműbb működését érhetjük el, ha a szerializálandó osztályunk implementálja az ISerializable interfészt. Ez egyetlen függvény megírását kéri tőlünk, a GetObjectData metódust, de ugyanúgy feltételez (lényegében igényel) ugyanekkor egy speciális paraméterezésű konstruktort is, melynek pedig a deszerializáció kapcsán lesz majd jelentősége.

public szemely(SerializationInfo info, StreamingContext context) {

nev = (string)info.GetValue("neve", typeof(string));

szul_ev = (int)info.GetValue("szuletett", typeof(int));

}

//Serialization function.

public void GetObjectData(SerializationInfo info, StreamingContext context) {

info.AddValue("neve", nev);

info.AddValue("szuletett", szul_ev);

} }

A szerializáció ekkor nem a korábban ismertett módon zajlik, nincs semmi automatizmus. A GetObjectData metódusban az info paraméterhez kell név-érték párosokat hozzáadni, melyek ugyanebben a formában kerülnek

kiírásra az XML dokumentumba. Tehát amely mezőt (értéket) hozzáadjuk, az belekerül az XML-be, amit nem, az nem kerül bele. Az objektum teljes egészében dönthet tehát saját maga szerializációjáról.

Az ily módon képzett kimenetben az is előfordulhat, hogy egyes mezők értékei nem a C#-beli mezők neveivel, hanem a fejlesztő által választott azonosítókkal. Ez esetben a deszerializáció sem fog működni, de nem is kell.

Amikor a visszaolvasás következik, nem az alapértelmezett konstruktort fogja használni a rendszer, hanem a speciális paraméterezésűt. Ekkor ellentétesen eljárva az info listából kiemelve az elemeket, típuskényszerítve visszaállíthatóak az értékek.