180 votes

Pourquoi la classe XML sérialisables besoin un constructeur sans paramètre

Je suis en train d'écrire du code pour faire de la sérialisation Xml. Avec, en dessous de la fonction.

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

Si l'argument est une instance de la classe sans constructeur sans paramètre, il va lancer une exception.

Exception Non Gérée: Système.InvalidOperationException: CSharpConsole.Toto ne peut pas être sérialisé parce qu'il ne dispose pas d'un constructeur sans paramètre. au Système.Xml.La sérialisation.TypeDesc.CheckSupported() au Système.Xml.La sérialisation.TypeScope.GetTypeDesc(Type type, MemberInfo sourc e, Boolean directReference, Boolean throwOnError) au Système.Xml.La sérialisation.ModelScope.GetTypeModel(Type type Boolean Référence directe) à Système.Xml.La sérialisation.XmlReflectionImporter.ImportTypeMapping(Type type , attribut xmlrootattribute racine, Chaîne defaultNamespace) à Système.Xml.La sérialisation.XmlSerializer..ctor(Type type, String defaultName de l'espace) à Système.Xml.La sérialisation.XmlSerializer..ctor(Type type)

Pourquoi doit-il y avoir un constructeur sans paramètre, afin de permettre la sérialisation xml pour réussir?

EDIT: merci pour cfeduke de réponse. Le constructeur sans paramètre ne peut être privé ou interne.

257voto

cfeduke Points 13153

Au cours de la désérialisation d’un objet, la classe responsable de la sérialisation d’un objet crée une instance de la classe sérialisée et procède ensuite à remplir les propriétés et les champs sérialisées seulement après l’acquisition d’une instance de remplir.

Vous pouvez faire votre constructeur ou si vous voulez, juste si longtemps comme sa sans paramètre.

77voto

Marc Gravell Points 482669

C'est une limitation de l' XmlSerializer. Notez que BinaryFormatter et DataContractSerializer n' exigent - ils peuvent créer un objet non initialisé de l'éther et de l'initialiser lors de la désérialisation.

Puisque vous êtes à l'aide de xml, vous pouvez envisager d'utiliser DataContractSerializer et le marquage de votre classe avec des [DataContract]/[DataMember], mais notez que cela change le schéma (par exemple, il n'y a pas d'équivalent de [XmlAttribute] - tout devient éléments).

Mise à jour: si vous voulez vraiment le savoir, BinaryFormatter et coll utiliser FormatterServices.GetUninitializedObject() de créer l'objet sans invoquer le constructeur. Peut-être dangereux; je ne recommande pas de l'utiliser trop souvent ;-p Voir également les remarques sur MSDN:

Parce que la nouvelle instance de l'objet est initialisée à zéro et aucune les constructeurs sont exécutés, l'objet pourrait représentent pas un état qui est considéré comme valide par cet objet. L'actuel la méthode doit être utilisée uniquement pour la désérialisation lorsque l'utilisateur a l'intention immédiatement remplir tous les champs. Il ne pas créer un non initialisée chaîne, depuis la création d'un vide exemple d'une immuable type de dessert pas de but.

J'ai mon propre moteur de sérialisation, mais je n'ai pas l'intention de la faire, utilisez FormatterServices; j'aime assez, sachant qu'un constructeur (tout constructeur) a effectivement exécutées.

0voto

Dmitry Khalatov Points 2172

Tout d’abord, ce qui est écrit dans la documentation. Je pense que c’est l’un de vos champs de classe, pas celui principal - et comment vous voulez deserialiser pour sa construction retour w/o construction sans paramètre ?

Je pense qu’il existe une solution pour rendre le constructeur privé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X