tutorials.de Buch-Aktion 05/2012
Like Tree1Danke
  • 1 Beitrag von Spyke
ERLEDIGT
JA
ANTWORTEN
6
ZUGRIFFE
408
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von Shakie
    Shakie Shakie ist offline Mitglied Diamant
    Registriert seit
    May 2004
    Ort
    Europa
    Beiträge
    2.048
    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:
    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;
    Wobei "LokaleKlasse" so definiert ist:
    Code csharp:
    1
    2
    3
    4
    5
    
    // Assembly Hauptprogramm.exe
    public class LokaleKlasse
    {
        public object plugin { get; set; }
    }
    Und PluginKlasse so:
    Code csharp:
    1
    2
    3
    4
    5
    
    // Assembly ClassLibrary1
    public class PluginKlasse
    {
        public String Information {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.
    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; }
    }
    Code csharp:
    1
    2
    3
    4
    5
    
    // Assembly ClassLibrary1:
    public class PluginKlasse : Hauptprogramm.LeereKlasse
    {
        public String Information {get; set; }
    }
    Die Serialisierung funktioniert dann problemlos so:
    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);
        }
    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...
     

  2. #2
    Avatar von Spyke
    Spyke Spyke ist offline Capoeirista
    Registriert seit
    Oct 2002
    Beiträge
    931
    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).
     
    www.iv-interactive.de - Projektewebsite
    WikiParser - aktuelles Projekt

  3. #3
    Avatar von Nico Graichen
    Nico Graichen Nico Graichen ist offline aka gemballa
    tutorials.de Moderator
    Registriert seit
    Dec 2003
    Ort
    Pulheim (NRW)
    Beiträge
    3.898
    Blog-Einträge
    34
    Hi

    Alternativ das Interface IXmlSerializable implementieren und darüber die (De)Serialisierung selbst steuern.
     
    Grüße Nico
    ----------------------
    Xing
    ----------------------
    Zitat Zitat von Mark Twain (1835-1910)
    Es gibt drei Dinge, die eine Frau aus dem Nichts hervorzaubern kann: einen Hut, einen Salat und einen Ehekrach.
    Zitat Zitat von Mike Wilson - Biographie über Larry Ellison (CEO Oracle)
    The Difference Between God and Larry Ellison: God Doesn't Think He's Larry Ellison

  4. #4
    Avatar von Shakie
    Shakie Shakie ist offline Mitglied Diamant
    Registriert seit
    May 2004
    Ort
    Europa
    Beiträge
    2.048
    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
    1. ich dann für alle Child-Objekte ebenfalls IXmlSerializable implementieren muss
    2. und mir die korrekte Implementierung des Interfaces aufwendig erscheint, nachdem ich das hier gelesen habe
    Ich weiß nicht so recht für welche Vorgehensweise ich mich nun entscheiden soll
    EDIT: Bezüglich SoapFormatter, da musste ich mir erst mal den Wiki-Eintrag durchlesen, wass SOAP überhaupt ist:
    Zitat Zitat von Wikipedia
    SOAP ist ein Protokoll zum Austausch XML-basierter Nachrichten [...]
    Ich vermute, intern benutzt der SoapFormatter also erst einen XMl-Serializer?
    Geändert von Shakie (15.11.10 um 12:41 Uhr)
     

  5. #5
    Avatar von Spyke
    Spyke Spyke ist offline Capoeirista
    Registriert seit
    Oct 2002
    Beiträge
    931
    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.
    Shakie bedankt sich. 
    www.iv-interactive.de - Projektewebsite
    WikiParser - aktuelles Projekt

  6. #6
    Avatar von Nico Graichen
    Nico Graichen Nico Graichen ist offline aka gemballa
    tutorials.de Moderator
    Registriert seit
    Dec 2003
    Ort
    Pulheim (NRW)
    Beiträge
    3.898
    Blog-Einträge
    34
    Zitat Zitat von Shakie Beitrag anzeigen
    Und vor IXmlSerializable habe ich mich gescheut, da
    1. ich dann für alle Child-Objekte ebenfalls IXmlSerializable implementieren muss
    Nur die, die du auch serialisieren willst und nicht bereits IXmlSerializable implementieren (machen schon viele .NET-Klassen)
     
    Grüße Nico
    ----------------------
    Xing
    ----------------------
    Zitat Zitat von Mark Twain (1835-1910)
    Es gibt drei Dinge, die eine Frau aus dem Nichts hervorzaubern kann: einen Hut, einen Salat und einen Ehekrach.
    Zitat Zitat von Mike Wilson - Biographie über Larry Ellison (CEO Oracle)
    The Difference Between God and Larry Ellison: God Doesn't Think He's Larry Ellison

  7. #7
    Avatar von Shakie
    Shakie Shakie ist offline Mitglied Diamant
    Registriert seit
    May 2004
    Ort
    Europa
    Beiträge
    2.048
    Danke für eure Hilfe, ich habe mich nun für den BinaryFormatter und das ISerializable-Interface entschieden!
     

Ähnliche Themen

  1. Geladene Schriftart erkennen
    Von Jan-Frederik Stieler im Forum Javascript & Ajax
    Antworten: 1
    Letzter Beitrag: 17.03.10, 19:01
  2. Geladene Bilder hinter MCs
    Von mafiamix im Forum Flash Plattform
    Antworten: 5
    Letzter Beitrag: 25.10.09, 00:44
  3. Extern geladene SWF skalieren
    Von mogmog im Forum Flash Plattform
    Antworten: 4
    Letzter Beitrag: 17.04.07, 18:14
  4. ScrollPane geladene jpg-Datei
    Von Amateur2000 im Forum Java
    Antworten: 1
    Letzter Beitrag: 09.05.05, 15:26
  5. ScrollPane geladene jpg-Datei
    Von GS1 im Forum Flash Plattform
    Antworten: 2
    Letzter Beitrag: 20.04.05, 15:02

Stichworte