Tengo un problema muy extraño al trabajar con .NET XmlSerializer
.
Tome las siguientes clases de ejemplo:
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, hay tres métodos diferentes para resolver el problema InvalidOperationException
causado por el serializador que no conoce los tipos derivados de Payment
.
1. Añadiendo XmlInclude
a la Payment
definición de clase:
Esto no es posible debido a que todas las clases se incluyen como referencias externas sobre las que no tengo control.
2. Pasar los tipos de tipos derivados durante la creación de la XmlSerializer
instancia
No funciona.
3. Definición XmlAttributeOverrides
de la propiedad de destino para anular la serialización predeterminada de la propiedad (como se explica en esta publicación SO )
Tampoco funciona ( XmlAttributeOverrides
sigue la inicialización).
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);
XmlSerializer
Entonces se usaría el constructor apropiado .
NOTA: por no funciona me refiero a que se lanza InvalidOperationException
( BankPayment
no se esperaba ... ).
¿Alguien puede arrojar algo de luz sobre el tema? ¿Cómo se procedería a depurar más el problema?
fuente
Acabo de resolver el problema. Después de investigar un poco más, encontré esta publicación SO que cubre exactamente la misma situación. Me puso en el camino correcto.
Básicamente, es
XmlSerializer
necesario conocer el espacio de nombres predeterminado si las clases derivadas se incluyen como tipos adicionales. La razón exacta por la que esto tiene que suceder aún se desconoce, pero, aún así, la serialización está funcionando ahora.fuente
Estoy de acuerdo con bizl
Además, si necesita aplicar esta clase incluida a un elemento de objeto, puede hacerlo así
fuente
Simplemente hágalo en la Base, de esa manera cualquier niño puede ser serializado, menos código limpiador de código.
De esta manera, puede llamar a Serialize en la clase secundaria sin importar las circunstancias y aún así poder hacer lo que necesita antes de que el objeto Serialize.
fuente
En base a esto , pude resolver esto cambiando el constructor
XmlSerializer
que estaba usando en lugar de cambiar las clases.En lugar de usar algo como esto (sugerido en las otras respuestas):
Hice esto:
fuente