C# - SOAP szerializáció

forráskód letöltése
Az objektumokban tárolt információ mentésének leghatékonyabb formája a szerializáció, melynek eredménye egy XML állomány, ahol az egyes tagobjektumok értékei az állomány tagjaiban jelennek meg. Az objektumok szerializációjának egy különleges formáját mutatjuk be cikkünkben a SoapAttributeOverrides osztály felhasználásával. A mentés lényege, hogy magunk határozhatjuk meg a tárolandó tagobjektumok körét, vagyis van lehetőségünk bizonyos elemek kihagyására, vagy a tárolandó tartalom felülírására, amire a hagyományos mentéskor nincs módunk.
A mellékelt példában egy Csoport nevű osztály példányát szerializáljuk, melynek tagjait (tagváltozók, tagobjektumok) SOAP attribútumokkal láttuk el, így biztosítva hogy később a bevezetőben említett osztály felhasználásával befolyásoljuk mentésüket.
A program két füle alatt a MENTÉS gombokkal végezhetjük el az objektum mentését egy XML állományba, majd a VISSZAOLVASÁS gombbal az állomány visszatöltése indítható el.
Az alkalmazás SerializeClass osztályában helyeztük el a műveleteket végző statikus metódusokat. De vizsgáljuk meg először a szerializálandó osztályt. Az osztály tagjai a következők:
Első tag egy karakterlánc, mely a csoport nevét tartalmazza.
public class Csoport
{
  [SoapAttribute (Namespace = "http://www.softwareonline.hu")]
  public string CsoportNev;
Szintén SoapAttribute megjelöléssel egy bájttömb, a csoport számával.
  [SoapAttribute(DataType = "base64Binary")]
  public Byte [] CsoportSzam;
Tartalmaz egy SoapElement attribútummal rendelkező tagot.
  [SoapElement(DataType = "nonNegativeInteger", ElementName = "TagokSzama")]
  public string TagSzam;
A SoapIgnore attribútummal rendelkező tag esetén van lehetőség a mentéskor rendelkezni arról, hogy bekerül-e a mentett állományba, vagy sem.
  [SoapIgnore] 
  public bool Mukodik;
  ...
}
A SerializeClass osztályban az SOriginal nevű metódus végzi el a szerializáció hagyományos formáját, melyben ugyan SOAP szerializációt végzünk, de nincs lehetőség az egyes tagok mentésével kapcsolatban arra, hogy felülírjuk az attribútumokban megadott rendelkezéseket.
Az XmlTypeMapping osztály segítségével térképezzük fel a szerializálandó típust.
XmlTypeMapping mapping = (new SoapReflectionImporter().ImportTypeMapping(typeof(Csoport)));
Majd felhasználásával létrehozunk egy XmlSerializer objektumot.
XmlSerializer serializer = new XmlSerializer(mapping);
Szükségünk van egy objektumba, mely az állományhoz rendelt adatfolyamba írja a bájtfolyamot.
TextWriter writer = new StreamWriter("SOriginal.xml");
A metódus két bemenő paramétere a Form két szövegmezőjében megadható értéket tartalmazza, ezeket most megadjuk a mentendő objektum megfelelő tagjaiban.
Csoport cs = new Csoport();
cs.CsoportNev = csoportnev;
cs.CsoportSzam = Convert.FromBase64String(csoportszam);
...
Miután a többi tag is értéket kapott elvégezzük a műveletet.
serializer.Serialize(writer, cs);
writer.Close();
A DOriginal metódusban a visszaolvasás kódját helyeztük el, mely csak abban különbözik, hogy itt egy TextReader objektum végzi a kiolvasást az adatfolyamból, valamint a Deserialize metódust hívjuk meg.
TextReader reader = new StreamReader("SOriginal.xml");
Csoport cs; 
cs = (Csoport)serializer.Deserialize(reader);
...
A felülíró szerializáció elvégzése előtt készítenünk kell egy saját szerializáló objektumot a CreateSerializer metódus segítésével. Ebben rendelkezünk arról, hogy az egyes attribútumokkal megjelölt tagváltozókat hogyan szerializáljuk.
Példányosítjuk a SoapOverrideAttributes osztályt.
SoapAttributeOverrides attrOverrides = new SoapAttributeOverrides();
Létrehozunk egy objektumot az attribútumok listája számára.
SoapAttributes soapAttr = new SoapAttributes();
Hozzáadhatunk egy új elemet a szerializált objektumhoz.
SoapElementAttribute soapElement = new SoapElementAttribute();
soapElement.ElementName = "UjElem";
soapAttr.SoapElement = soapElement;
A SoapIgnore attribútummal megjelölt elem normális esetben kimaradna a tárolandó tagok listájából, azonban itt ezt a rendelkezésünket is megváltoztathatjuk.
SoapIgnoreAttribute ignore = new SoapIgnoreAttribute();
soapAttr = new SoapAttributes();
soapAttr.SoapIgnore = false;      
attrOverrides.Add(typeof(Csoport), "Mukodik", soapAttr);
Felülírhatjuk a felsorolt típusok definícióit is.
soapAttr = new SoapAttributes();
SoapEnumAttribute soapEnum = new SoapEnumAttribute();
soapEnum.Name = "FelulirtCsoportTipus";
soapAttr.SoapEnum = soapEnum;
attrOverrides.Add(typeof(CsoportTipus), "nagycsoport", soapAttr);
Még az állomány főcsomópontjának megnevezését – ami alapesetben a mentendő objektum típusának neve - is módosíthatjuk.
soapAttr = new SoapAttributes();
SoapTypeAttribute soapType = new SoapTypeAttribute();
soapType.TypeName = "Team";
soapAttr.SoapType = soapType;
attrOverrides.Add(typeof(Csoport),soapAttr);
Végül létrehozzuk az ily módon képzett minta alapján a szerializáló objektumot.
XmlTypeMapping mapping = (new SoapReflectionImporter(attrOverrides)).ImportTypeMapping(typeof(Csoport));
XmlSerializer serializer = new XmlSerializer(mapping);
return serializer;
A SOverride metódusban már ezt a felülírt tulajdonságú objektumot használjuk fel a mentésre, a többi művelet nem változik.
public static void SOverride(string csoportnev, string csoportszam)
{
  XmlSerializer oserializer = CreateSerializer();
  ...
}
Csakúgy, mint a DOverride felülírt deszerializációt megvalósító metódusban.
public static void DOverride(out string csoportnev, out string csoportszam)
{
  XmlSerializer oserializer = CreateSerializer();
  ...
}
A kétfajta szerializációt használó művelet eredménye egy-egy XML állomány, melyek a futtatható állomány mellé kerülnek. Felépítésükből jól látszik a két művelet közti eltérés.