J'ai un problème très étrange lorsque je travaille avec .NET XmlSerializer
.
Prenez les exemples de classes suivants:
public class Order
{
public PaymentCollection Payments { get; set; }
//everything else is serializable (including other collections of non-abstract types)
}
public class PaymentCollection : Collection<Payment>
{
}
public abstract class Payment
{
//abstract methods
}
public class BankPayment : Payment
{
//method implementations
}
AFAIK, il existe trois méthodes différentes pour résoudre le problème InvalidOperationException
causé par le sérialiseur ne sachant pas les types dérivés de Payment
.
1. Ajout XmlInclude
à la Payment
définition de classe:
Cela n'est pas possible car toutes les classes sont incluses en tant que références externes sur lesquelles je n'ai aucun contrôle.
2. Passer les types des types dérivés lors de la création de l' XmlSerializer
instance
Ça ne marche pas.
3. Définition XmlAttributeOverrides
de la propriété cible afin de remplacer la sérialisation par défaut de la propriété (comme expliqué dans cet article SO )
Ne fonctionne pas non plus (l' XmlAttributeOverrides
initialisation suit).
Type bankPayment = typeof(BankPayment);
XmlAttributes attributes = new XmlAttributes();
attributes.XmlElements.Add(new XmlElementAttribute(bankPayment.Name, bankPayment));
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Order), "Payments", attributes);
Le XmlSerializer
constructeur approprié serait alors utilisé.
REMARQUE: par ne fonctionne pas, je veux dire que le InvalidOperationException
( BankPayment
n'était pas prévu ... ) est lancé.
Quelqu'un peut-il faire la lumière sur le sujet? Comment procéder et déboguer davantage le problème?
la source
Je viens de résoudre le problème. Après avoir fouillé un peu plus longtemps, j'ai trouvé ce message SO qui couvre exactement la même situation. Cela m'a mis sur la bonne voie.
Fondamentalement, il est
XmlSerializer
nécessaire de connaître l'espace de noms par défaut si les classes dérivées sont incluses en tant que types supplémentaires. La raison exacte pour laquelle cela doit se produire est encore inconnue mais, toujours, la sérialisation fonctionne maintenant.la source
Je suis d'accord avec bizl
aussi si vous devez appliquer cette classe incluse à un objet objet, vous pouvez faire comme ça
la source
Faites-le simplement dans la base, de cette façon tout enfant peut être sérialisé, moins de code plus propre.
De cette façon, vous pouvez appeler Serialize sur la classe enfant quelle que soit la circonstance et toujours pouvoir faire ce dont vous avez besoin avant que l'objet ne soit sérialisé.
la source
Sur cette base, j'ai pu résoudre ce problème en changeant le constructeur que
XmlSerializer
j'utilisais au lieu de changer les classes.Au lieu d'utiliser quelque chose comme ça (suggéré dans les autres réponses):
J'ai fait ça:
la source