it-swarm.com.de

Warum XML-Serializable-Klassen einen parameterlosen Konstruktor benötigen

Ich schreibe Code für die XML-Serialisierung. Mit unten funktion.

public static string SerializeToXml(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

Wenn das Argument eine Instanz einer Klasse ohne parameterlosen Konstruktor ist, wird eine Ausnahme ausgelöst.

Nicht behandelte Ausnahme: System.InvalidOperationException: CSharpConsole.Foo kann nicht serialisiert werden, da kein parameterloser Konstruktor vorhanden ist. bei System.Xml.Serialization.TypeDesc.CheckSupported () bei System.Xml.Serialization.TypeScope.GetTypeDesc (Typtyp, MemberInfo-Quelle, Boolean directReference, Boolean throwOnError) bei System.Xml.Serialization.ModelScope.GetTypeModel () Boolesche direkte Referenz) unter System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (Typtyp, XmlRootAttribute-Stammverzeichnis, String defaultNamespace) unter System.Xml.Serialization.XmlSerializer..ctor (Typtyp, String defaultName-Leerzeichen) unter System.Xml.Serialization. XmlSerializer..ctor (Typ Typ)

Warum muss es einen parameterlosen Konstruktor geben, damit die XML-Serialisierung erfolgreich ist?

EDIT: danke für die antwort von cfeduke. Der parameterlose Konstruktor kann privat oder intern sein.

167
Morgan Cheng

Während der Deserialisierung eines Objekts erstellt die Klasse, die für die Deserialisierung eines Objekts verantwortlich ist, eine Instanz der serialisierten Klasse und füllt die serialisierten Felder und Eigenschaften erst dann auf, nachdem sie eine zu füllende Instanz erfasst hat.

Sie können Ihren Konstruktor zu private oder internal machen, wenn Sie möchten, nur solange er parameterlos ist.

234
cfeduke

Dies ist eine Einschränkung von XmlSerializer. Beachten Sie, dass BinaryFormatter und DataContractSerializer dies nicht erfordern - sie können ein nicht initialisiertes Objekt aus dem Äther erzeugen und initialisieren es während der Deserialisierung.

Da Sie XML verwenden, können Sie die Verwendung von DataContractSerializer in Betracht ziehen und Ihre Klasse mit [DataContract]/[DataMember Markieren äquivalent zu [XmlAttribute] - alles wird zu Elementen).

Update: Wenn Sie wirklich wissen möchten, verwenden Sie BinaryFormatter ua FormatterServices.GetUninitializedObject() , um das Objekt zu erstellen, ohne den Konstruktor aufzurufen. Wahrscheinlich gefährlich; Ich empfehle es nicht zu oft zu verwenden ;-p Siehe auch die Anmerkungen zu MSDN:

Da die neue Instanz des Objekts auf Null initialisiert wird und keine Konstruktoren ausgeführt werden, stellt das Objekt möglicherweise keinen Status dar, der von diesem Objekt als gültig angesehen wird. Die aktuelle Methode sollte nur zur Deserialisierung verwendet werden, wenn der Benutzer beabsichtigt, alle Felder sofort zu füllen. Es wird keine nicht initialisierte Zeichenfolge erstellt, da das Erstellen einer leeren Instanz eines unveränderlichen Typs keinen Zweck erfüllt.

Ich habe meine eigene Serialisierungs-Engine, aber ich beabsichtige nicht, FormatterServices zu verwenden. Ich mag es sehr zu wissen, dass ein Konstruktor ( ein beliebiger Konstruktor) tatsächlich ausgeführt hat.

73
Marc Gravell

Zuallererst ist dies, was in Dokumentation geschrieben ist. Ich denke, es ist eines Ihrer Klassenfelder, nicht das Hauptfeld - und wie soll es von Deserialisierern ohne parameterlose Konstruktion wiederhergestellt werden?

Ich denke, es gibt eine Problemumgehung, um Konstruktor privat zu machen.

0
Dmitry Khalatov