Shakie
Erfahrenes Mitglied
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:
Und PluginKlasse so:
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:
Die Serialisierung funktioniert dann problemlos so:
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...
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:
C#:
Assembly a = Assembly.LoadFile("C:\\ClassLibrary1.dll");
object plugin = a.CreateInstance("ClassLibrary1.PluginKlasse");
LokaleKlasse lokal = new LokaleKlasse();
lokal.plugin = plugin;
C#:
// Assembly Hauptprogramm.exe
public class LokaleKlasse
{
public object plugin { get; set; }
}
C#:
// 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:
C#:
// Assembly Hauptprogramm.exe
public class LeereKlasse {}
public class LokaleKlasse
{
public LeereKlasse plugin { get; set; }
}
C#:
// Assembly ClassLibrary1:
public class PluginKlasse : Hauptprogramm.LeereKlasse
{
public String Information {get; set; }
}
C#:
// 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);
}