-
Vorab: Ich habe für mein Problem schon eine Lösung, aber ich finde sie nicht schön.
Zum Problem:
Ich habe eine Art Plugin-System. Ich lade eine DLL dynamisch und instanziiere eine Klasse aus dieser DLL. Diese Instanz weise ich einem Member einer anderen Klasse aus einer anderen Assembly zu:
Wobei "LokaleKlasse" so definiert ist:Code csharp:1 2 3 4
Assembly a = Assembly.LoadFile("C:\\ClassLibrary1.dll"); object plugin = a.CreateInstance("ClassLibrary1.PluginKlasse"); LokaleKlasse lokal = new LokaleKlasse(); lokal.plugin = plugin;
Und PluginKlasse so:Code csharp:1 2 3 4 5
// Assembly Hauptprogramm.exe public class LokaleKlasse { public object plugin { get; set; } }
Nun möchte ich die Instanz "lokal" mit dem XmlSerializer serialisieren, wo das Problem anfängt. Der XmlSerializer weiß nicht, was er mit dem plugin-Member tun soll, da es in "LokaleKlasse" lediglich als Object definiert ist.Code csharp:1 2 3 4 5
// Assembly ClassLibrary1 public class PluginKlasse { public String Information {get; set; } }
Glücklicherweise gibt es einen überladenen Konstruktor des XmlSerializers, der ein Array von zusätzlichen Typen erwartet. Der XmlSerializer sollte dann prüfen, ob ein Instanztyp, mit der er nichts anfangen kann, vielleicht ein Typ aus diesem Array ist. Sollte... Das funktioniert nur, wenn der Basistyp nicht System.Object ist, sondern irgendwas anderes, was in der selben Assembly definiert ist wie die Klasse "LokaleKlasse". Jedenfalls war das bei meinen Tests so.
Meine Frage am Ende dieses Posts wird sein, ob das nicht auch hübscher geht als so, wie ich es jetzt gelöst habe: nämlich in der Assembly von LokaleKlasse eine "LeereKlasse" zu definieren, die nichts weiter tut außer zu existieren und von der meine Plugin-Klasse (PluginKlasse) ableitet:
Code csharp:1 2 3 4 5 6 7
// Assembly Hauptprogramm.exe public class LeereKlasse {} public class LokaleKlasse { public LeereKlasse plugin { get; set; } }
Die Serialisierung funktioniert dann problemlos so:Code csharp:1 2 3 4 5
// Assembly ClassLibrary1: public class PluginKlasse : Hauptprogramm.LeereKlasse { public String Information {get; set; } }
Aber ist das wirklich so gedacht, dass ich den Umweg über die "LeereKlasse" gehen muss? Man sollte meinen, dass ich eine leere Klasse einfach durch den Typ System.Object hätte ersetzen können...Code csharp:1 2 3 4 5 6 7 8 9 10 11 12 13
// Zuerst dynamisch eine Instanz erzeugen (wie oben) Assembly a = Assembly.LoadFile("C:\\ClassLibrary1.dll"); object plugin = a.CreateInstance("ClassLibrary1.PluginKlasse"); LokaleKlasse lokal = new LokaleKlasse(); lokal.plugin = plugin; // Serialisierer instanziieren XmlSerializer ser = new XmlSerializer(typeof(LokaleKlasse), new Type[] {lokal.plugin.GetType() }); // StreamWriter zum Schreiben in Datei instanziieren using (System.IO.StreamWriter writer = new System.IO.StreamWriter("C:\\test.xml")) { // und letztendlich serialisieren ser.Serialize(writer, lokal); }
-
Muss es XMlSerialize sein ich würde eher BinaryFormatter (oder SoapFormatter, abermit dem habe ich noch nicht gearbeitet) verwenden.
Der geht nicht auf die Eigenschaften sondern auf die Felder und serialisiert diese.
Der würde auch mit objekt klar kommen solange das SerializableAttribute oder ISerializable bei dem Objekt gesetzt ist.
Darüber hinaus musst du beim XmlSerializer bei Enums aufpassen da dieser nicht den Feldwert speichert, sondern den Feldnamen.
Hatte mir schon einige Probleme bereitet (Gibt aber ein Attribute um dies zu ändern, XmlEnumAttribute glaube).
-
Hi
Alternativ das Interface IXmlSerializable implementieren und darüber die (De)Serialisierung selbst steuern.Grüße Nico
----------------------
Xing
----------------------
Zitat von Mark Twain (1835-1910)
Zitat von Mike Wilson - Biographie über Larry Ellison (CEO Oracle)
-
Es kann sein, dass die Klasse in eine Datei serialisiert wird und beim Deserialisieren aber nicht mehr alle Plugins vorhanden sind (z.B. weil der Benutzer eine Plugin-DLL gelöscht hat). Es soll dann aber immer noch möglich sein die Datei halbwegs zu laden, so gut es halt geht. Mit dem BinaryFormatter wüsste ich nicht wie ich das anstelle. Ich hoffe, dass das mit dem XmlSerializer besser geht - ich habe mich noch nicht so detailliert mit ihm beschäftigt.
Und vor IXmlSerializable habe ich mich gescheut, da- ich dann für alle Child-Objekte ebenfalls IXmlSerializable implementieren muss
- und mir die korrekte Implementierung des Interfaces aufwendig erscheint, nachdem ich das hier gelesen habe

EDIT: Bezüglich SoapFormatter, da musste ich mir erst mal den Wiki-Eintrag durchlesen, wass SOAP überhaupt ist:Ich vermute, intern benutzt der SoapFormatter also erst einen XMl-Serializer?
Zitat von Wikipedia
Geändert von Shakie (15.11.10 um 12:41 Uhr)
-
Keine Ahnung

Zum BinaryFormatter:
Am besten ist es die ISerializable Schnittstelle bei deinem Plugin System zu implementieren.
Über die GetObjectData Methode setzt du einfach die Werte ins SerializationInfo die serialisiert werden soll.
Das wichtige hierbei ist aber eigentlich das man einen Kostructor anlegen muss der SerializationInfo und StreamingContext context als Parameter erwartet um die Daten aus SerializationInfo wieder auszulesen.
Sprich du bist nicht mehr ganz Klassen und Namespace abhängig.
-
Grüße Nico
----------------------
Xing
----------------------
Zitat von Mark Twain (1835-1910)
Zitat von Mike Wilson - Biographie über Larry Ellison (CEO Oracle)
-
Danke für eure Hilfe, ich habe mich nun für den BinaryFormatter und das ISerializable-Interface entschieden!
Ähnliche Themen
-
Geladene Schriftart erkennen
Von Jan-Frederik Stieler im Forum Javascript & AjaxAntworten: 1Letzter Beitrag: 17.03.10, 19:01 -
Geladene Bilder hinter MCs
Von mafiamix im Forum Flash PlattformAntworten: 5Letzter Beitrag: 25.10.09, 00:44 -
Extern geladene SWF skalieren
Von mogmog im Forum Flash PlattformAntworten: 4Letzter Beitrag: 17.04.07, 18:14 -
ScrollPane geladene jpg-Datei
Von Amateur2000 im Forum JavaAntworten: 1Letzter Beitrag: 09.05.05, 15:26 -
ScrollPane geladene jpg-Datei
Von GS1 im Forum Flash PlattformAntworten: 2Letzter Beitrag: 20.04.05, 15:02



1Danke

Zitieren


Login





