Como posso forçar o uso de um atributo xsi: type?
Como posso forçar o XmlSerializer do .NET a adicionar umxsi: type = "FooClass" para um membro / nó do tipoFooClass
?
O cenário é um aplicativo atualmente lançado, em que na v.1:
FooClass herda FooBaseClassFooPropertyA está no FooBaseClassFooPropertyB está no FooClassFooBaseClass é decorado com [XmlInclude (typeof (FooClass))]BazClass tem membro Foo do tipo FooBaseClassTodos os conjuntos de Baz.Foo são para uma instância FooClassTodos os usos de Baz.Foo esperam FooPropertyB (e, portanto, uma ocorrência FooClass vs FooBaseClass)O objetivo: Remover FooBaseClass inteiramente, empurrando os membros do FooBaseClass para o FooClass,mantendo a compatibilidade de serialização retroativa
O problema: Então eu perco o atributo xsi: type = "FooClass" na serialização Baz.Foo.
Em outras palavras, a saída XmlSerializer.Serialize de
public class BazClass
{
public BazClass()
{
Foo = new FooClass { A = 5, B = "Hello" };
}
public FooClass Foo { get; set; }
}
public class FooClass
{
public int FooPropertyA { get; set; }
public string FooPropertyB { get; set; }
}
precisa ser
<Baz>
<Foo xsi:type="FooClass">
<FooPropertyA>Hello</FooPropertyA>
<FooPropertyB>5</FooPropertyB>
</Foo>
</Baz>
A remoção de FooBasClass é fácil, mas o XmlSerializer não coloca mais xsi: type = "FooClass" no Baz / Foo e, portanto, v.1 XmlSerializer.Deserialize instancia uma ocorrência de FooBaseClass, não definindo FooPropertyB, e atribui à propriedade Foo do pai Instância de Baz. Assim, qualquer código que verifique se o Baz.Foo é FooClass, ou lança diretamente, falhará.
O atributo xsi: type foi colocado automaticamente no código v.1 que estava
public class BazClass
{
public BazClass()
{
Foo = new FooClass { A = 5, B = "Hello" };
}
public FooBaseClass Foo { get; set; }
}
public class FooClass : FooBaseClass
{
public string FooPropertyB { get; set; }
}
[XmlInclude(typeof(FooClass))]
public class FooBaseClass
{
public int FooPropertyA { get; set; }
}
Eu acho que a resposta curta é que você não pode - pelo menos não sem implementar I (Xml) Serializable ou escrever código de serialização personalizado. No entanto, estou aberto a boas sugestões. Enquanto isso, eu implementei umsolução alternativa hackear abaixo, e estou esperando por algo mais elegante, ou que pelo menos me permita de alguma forma remover FooBaseClass inteiramente.
BazClass
{
[XmlElement("Foo")]
public FooBaseClass XmlFoo { get { return Foo; } set { Foo = (StartPicture)value; } }
[XmlIgnore]
public FooClass Foo { get; set; }
}
FooClass : FooBaseClass
{
public int FooPropertyB { get; set; }
public string FooPropertyA { get; set; }
}
[XmlInclude("FooClass")]
FooBaseClass
{
}