Eu tenho um problema muito estranho ao trabalhar com .NET XmlSerializer
.
Faça as seguintes classes de exemplo:
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, existem três métodos diferentes para resolver o problema InvalidOperationException
causado pelo serializador não saber sobre os tipos derivados de Payment
.
1. Adicionando XmlInclude
à Payment
definição da classe:
Isso não é possível porque todas as classes foram incluídas como referências externas sobre as quais não tenho controle.
2. Passando os tipos dos tipos derivados durante a criação da XmlSerializer
instância
Não funciona.
3. Definição XmlAttributeOverrides
da propriedade de destino para substituir a serialização padrão da propriedade (conforme explicado nesta postagem do SO )
Também não funciona (a XmlAttributeOverrides
inicialização segue).
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);
O XmlSerializer
construtor apropriado seria então usado.
NOTA: por não funcionar quero dizer que o InvalidOperationException
( BankPayment
não era esperado ... ) é jogado.
Alguém pode lançar alguma luz sobre o assunto? Como alguém faria para depurar o problema ainda mais?
fonte
Apenas resolveu o problema. Depois de vasculhar um pouco mais, encontrei este post do SO que cobre exatamente a mesma situação. Isso me colocou no caminho certo.
Basicamente, é
XmlSerializer
necessário saber o namespace padrão se as classes derivadas forem incluídas como tipos extras. O motivo exato pelo qual isso aconteceu ainda é desconhecido, mas, ainda assim, a serialização está funcionando agora.fonte
Eu concordo com o bizl
também se você precisar aplicar esta classe incluída a um item de objeto, você pode fazer assim
fonte
Basta fazer na Base, assim qualquer filho pode ser Serializado, menos código mais limpo.
Dessa forma, você pode chamar Serialize na classe filha, não importa a circunstância e ainda ser capaz de fazer o que você precisa antes de objeto Serializes.
fonte
Com base nisso , consegui resolver isso alterando o construtor
XmlSerializer
que estava usando em vez de alterar as classes.Em vez de usar algo assim (sugerido nas outras respostas):
Eu fiz isso:
fonte