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
{
}

questionAnswers(3)

yourAnswerToTheQuestion