Attribute Überblick - Attribute ermöglichen das Hinzufügen von benutzerdefinerbaren Informationen zur Klasse - analog der Sprache, Bsp.: ein schönes Auto - können zur Laufzeit abgefragt und ausgewertet werden - Attribute werden bei der Kompilierung in der Assembly durch Metadaten dargestellt - Verarbeitungsschritte - Definition - Verwendung (Attribuierung, deklarative Progr.) - Auswertung - Definition von Attributen: Attribute sind Klassen, die von System.Attribute abgeleitet werden - Namenskonvention: BezeichnerAttribute wobei Bezeichner beliebiger Name ist Prof. W. Henrich Seite 1
Attribute Verwendung - Attribute werden vor dem jeweiligen Element platziert, in eckigen Klammern - Bsp.: [Obsolete()] Element // d.h. Element hat // Attribut ObsoleteAttribute - Postfix Attribute des Namens kann entfallen (automatisch vom Compiler ergänzt) - Syntax der Attributverwendung gleicht Konstruktoraufruf class AutorAttribute : Attribute { public AutorAttribute(string name){...} } [Autor("WH")] // Klassenattribut class A{ [AutorAttribute("AH")] public void fn(){...} // Methodenattribut } Prof. W. Henrich Seite 2
Attribute Attributinformation in den Metadaten (ildasm) Attributinformation wird mit Reflection ausgewertet Prof. W. Henrich Seite 3
Attribute Auswertung der Attribute - Attributinformation wird mit Reflection ausgewertet (zusätzlicher Code ist somit zwingend erforderlich) static void Main(string[] args){ Type t = typeof(a); foreach(attribute attr in t.getcustomattributes(true)) { AutorAttribute auth = attr as AutorAttribute; if (auth!=null) Console.WriteLine("Typ: {0} {1}",t.Name,auth._name); } } // Ausgabe: Typ A WH - GetCustomAttributes(true) liefert Attribute des Typs Dies sind Instanzen der Attributklasse Prof. W. Henrich Seite 4
Attribute Konstruktoraufruf - Attribut muss mindestens einen Konstruktor haben - Attribute werden nur instanziiert (Aufruf des Konstruktors), falls sie ausdrücklich gesucht (Reflection) werden d.h. bei der Verwendung Ziel des Attributs (AttributeUsage) - teilt dem Compiler mit, wo Attribut verwendbar ist - AttributeUsage ist wiederum Attribut das auf Attribute angewendet wird (Meta-Attribut) - Attributziele: assembly, event, field, method, module, param, property, return, type [AttributeUsage(AttributeTargets.Class AttributeTargets.Field,Inherited = false,allowmultiple = false)] public class AutorAttribute : Attribute {...} Prof. W. Henrich Seite 5
Attribute Parameter der Attributverwendung - positionelle Parameter - Bsp.: [Obsolete("Text")] - werden durch Konstuktor übergeben - benannte Parameter - werden nach allen positionellen Parametern aufgeführt - der Name des Parameters muss angegeben werden Bsp.: [WebService(Namespace="http...")] [Autor(ID=4711, Hans )] <- falsch!! - werden als Eigenschaften (Property) implementiert - tatsächlich jedoch kein Konstruktoraufruf Prof. W. Henrich Seite 6
Attribute Klassifizierung der Attribute - benutzerdefinierte - werden von System.Attribute abgeleitet - können mit der Methode GetCustomAttributes(true); der Klasse Type ausgewertet werden Type t =...; // Attributinformation zum Typ t.getcustomattributes(true); oder: MemberInfo info =...; // zum Member Info.GetCustomAttributes(true); - intrinsische (vordefinierte) - sind Bestandteil der CLR Bsp.: Serialisierung über Attribut Serializable - Auswertung über Reflection ebenfalls möglich Prof. W. Henrich Seite 7
Attribute Vordefinierte Attribute (Beispiele) - [AttributeUsageAttribute] definiert Verwendungsmöglichkeiten eines Attributs - [Serializable] ermöglicht die Serialisierung einer Instanz, d. h. Instanzdaten werden in einen flachen Strom geschrieben - [Obsolete] Compiler erzeugt Warnung, dass Sprachelement veraltet ist - [WebMethod] Deklariert eine Methode als XML-Web-Service - [Conditional( debug )] Ist auf void Methoden anwendbar die ausgeführt werden falls Bedingung ( debug ) über #define gesetzt Prof. W. Henrich Seite 8
Attribute Attribute und Vererbung - Attribute können vererbt werden - Vererbung wird über das Metaattribut AttributeUsage gesteuert [AttributeUsage(AttributeTargets.Class...,Inherited = true,allowmultiple = true)] - mit Vererbung: Inherited = true - ohne Vererbung: Inherited = false - Falls Attribut mehrfach verwendet werden kann (AllowMultiple = true) kann das Attribut sowohl in der Basisklasse als auch in allen abgeleiteten Klassen gesetzt werden Prof. W. Henrich Seite 9
Serialisierung Serialisierung - Die Elemente des Objektes werden in Stream geschrieben - Die Serialisierung wird auch verwendet Stream beim Objekt - Schreiben in Datenbank oder - beim Marshaling über Grenzen (z. B. Prozessgrenzen) - CLR unterstützt Serialisierung eines Objektgraphen - Attribut: [Serializable] class Klassenname {Körper} ermöglicht Serialisierung - systemdefinierte Typen werden von der CLR richtig serialisiert - benutzerdefinierte Typen müssen explizit mit [Serializable] markiert werden - Deserialisierung: Erstellen von Instanzen aus serialisierten Objekten Objekt Zeichenfolge Zeichenfolge Objekt Stream Objekt Prof. W. Henrich Seite 10
Serialisierungsarten - innerhalb von.net Serialisierung - Ziel:.Net Objekt serialisiertes Objekt ->.Net Objekt d. h. serialisiertes Objekt stellt Zwischenstufe dar, die nicht näher interessiert (kann auch im XML- Format geschehen, aber dennoch in.net) - in XML (.Net wird verlassen!) -.Net Objekt wird in XML-Dokument transformiert.net Objekt XML-Dokument (.Net Objekt) - diese Darstellung ist nicht mehr objektorientiert - das XML-Dokument enthält keinen Bezug mehr zu.net und kann von beliebigen Klienten verarbeitet werden Prof. W. Henrich Seite 11
Serialisierung Serialisierung innerhalb von.net - Bei der Serialisierung muss eine Format in dem das Objekt gespeichert wird vereinbart werden - es erfolgt eine tiefe Serialisierung - alle Formatklassen implementieren Interface IFormatter - folgende Formate werden von der CLR unterstützt - binäres Format - SOAP Format - es können auch eigene Formatter-Klassen erstellt werden - Verwendung einer Formatterinstanz: Aufruf deren Methode Serialize(Stream, Objekt); - Bsp.: binformat.serialize(filestr,this); - Deserialisierung verwendet Formatter und liest aus Stream - Syntaxbsp.: binformat.deserialize(filestr); Prof. W. Henrich Seite 12
Serialisierung SOAP Serialisierung/Deserialisierung [Serializable] class A { public A(int j){i=j;} public int i; static void Main(string[] args){ A a = new A(5); FileStream myfile; myfile = new FileStream("C:test.dat", FileMode.Create); SoapFormatter dasformat = new SoapFormatter(); dasformat.serialize(myfile,a); myfile.close(); myfile = new FileStream("C:test.dat", FileMode.Open); A aneu = (A) dasformat.deserialize(myfile); myfile.close();} } Prof. W. Henrich Seite 13
Die Serialisierten Daten Serialisierung <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:soap-enc="http:// schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="http://schemas. xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/ soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap. org/soap/encoding/"> <SOAP-ENV:Body> <a1:a id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ Attribut/Attribute%2C%20Version%3D1.0.1812.21135%2C%20Culture%3Dneutral% 2C%20PublicKeyToken%3Dnull"> <i>5</i> </a1:a> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Full qualified Typename TypeName und AssemblyName Prof. W. Henrich Seite 14
Serialisierung Zusammenfassung: Vorgehensweise bei der Serialisierung 1. Markieren einer Klasse mit dem Attribut [Serializable] (Systemdefinierte Typen werden automatisch richtig serialisiert) Markieren nicht zu serialisierender Variablen mit dem Attribut [NonSerialized()] 2. Instanziieren einer Formatterklasse (Binary, Soap,Xml) 3. Aufruf der Methode Serialize des Formatter-Objektes (pro zu serialisierender Instanz, alternativ kann Collection serialisiert werden) 4. Zur Deserialisierung: Aufruf der Methode Deserialize des Formatter-Objektes (sowie casten, da object zurückgegeben wird) (bei mehreren Objekten mehrmals aufrufen) Prof. W. Henrich Seite 15
Serialisierung Die Schnittstelle ISerializable - ermöglicht Steuerung des WAS der Serialisierung - ISerializable enthält GetObjectData() - Zur Deserialisierung ist spezieller Deserialisierungs- Konstruktor nötig - Vorsicht falls tiefe Kopie erforderlich! [Serializable] class A: ISerializable { public int i; public void GetObjectData(SerializationInfo info, StreamingContext context) {info.addvalue ("i", i+10);} protected A (SerializationInfo si, StreamingContext sct) {i = si.getint32 ("i")-10;}... static void Main(string[] args){...} // unverändert } Prof. W. Henrich Seite 16
Serialisierung Ergänzungen zur Serialisierung in.net - Steuerung der Formatierung der Serialisierung durch eigene Formatterklasse (abgeleitet von IFormatter) - Serialisierung und Deserialisierung mehrerer Instanzen ist möglich - Jeder Aufruf von Serialize() hängt einen neues Root- Element <SOAP-ENV:Envelope>...</SOAP-ENV:Envelope> an den Stream an (=>XML-Soap Datei ist nicht wohlgeformt) - beherrscht zyklische Referenzen - Mit dem [NonSerialized] Attribut versehene Felder werden nicht serialisiert bzw. deserialisiert. - Attribut [Serializable] wird nicht vererbt, muss also in abgeleiteter und aggregierter Klasse gesetzt werden - Alle Serialisierungen verwenden Reflection Prof. W. Henrich Seite 17
Serialisierung Xml-Serialisierung - verarbeitet plattformunabhängies XML - Ausgabe kann über Attribute gut beeinflusst werden - Vorbedingungen: - zu serialisierende Klasse muss public sein - Klasse muss einen Standardkonstruktor definieren - Attribut [Serializable] muss nicht gesetzt sein (im Gegensatz zum Binary- und SOAPformatter) - Speichert nur public Fields und Read/Write Properties eines Objekts. Deserialisierte Objekte sind eventuell unvollständig. - Speichert keine Typinformation (keine Versionierung) - es kann Probleme mit zyklischen Referenzen geben - wird bei XML WebServices in.net verwendet Prof. W. Henrich Seite 18
Serialisierung Beispiel zur XML-Serialisierung public class A{ // public erforderlich public A(int j){i=j;} public A(){} // erforderlich public int i; static void Main(string[] args) { A a = new A(5); FileStream myfile; myfile = new FileStream("C:test.dat", FileMode.Create); XmlSerializer xmlser = new XmlSerializer(typeof(A)); xmlser.serialize(myfile,a); myfile.close(); myfile = new FileStream("C:test.dat", FileMode.Open); A aneu = (A) xmlser.deserialize(myfile); myfile.close(); } } Prof. W. Henrich Seite 19
Serialisierung XML serialisierte Instanz - reines XML keinerlei.net Informationen - kann von beliebigem Klienten verarbeitet werden natürlich auch von.net <?xml version="1.0"?> <A xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <i>5</i> </A> Prof. W. Henrich Seite 20