Jak wymusić użycie atrybutu xsi: type?

Jak mogę zmusić XmlSerializer .NET do dodaniaxsi: type = "FooClass" do członka / węzła typuFooClass?

Scenariusz to obecnie wydana aplikacja, w której w wersji 1:

FooClass dziedziczy FooBaseClassFooPropertyA jest na FooBaseClassFooPropertyB jest na FooClassFooBaseClass jest ozdobiony [XmlInclude (typeof (FooClass))]BazClass ma członka Foo typu FooBaseClassWszystkie zestawy Baz.Foo są instancją FooClassWszystkie zastosowania Baz.Foo oczekują FooPropertyB (a więc instancji FooClass vs FooBaseClass)

Cel: Całkowicie usuń FooBaseClass, wypychając członków FooBaseClass do FooClass,zachowując kompatybilność wsteczną serializacji

Problem: Następnie tracę atrybut xsi: type = "FooClass" w serializacji Baz.Foo.

Innymi słowy wyjście XmlSerializer.Serialize z

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

musi być

<Baz>
    <Foo xsi:type="FooClass">
        <FooPropertyA>Hello</FooPropertyA>
        <FooPropertyB>5</FooPropertyB>
    </Foo>
</Baz>

Usunięcie FooBasClass jest łatwe, ale wtedy XmlSerializer nie umieszcza już xsi: type = "FooClass" na Baz / Foo, więc v.1 XmlSerializer.Deserialize tworzy instancję FooBaseClass, nie ustawiając FooPropertyB i przypisuje ją do właściwości Foo rodzica Instancja Baz. Zatem każdy kod, który sprawdza, czy Baz.Foo jest FooClass, czy rzuca bezpośrednio, kończy się niepowodzeniem.

Atrybut xsi: type został umieszczony automatycznie w kodzie v.1

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

Myślę, że krótka odpowiedź jest taka, że ​​nie możesz - przynajmniej nie bez implementacji I (Xml) Serializable lub pisania niestandardowego kodu serializacji. Jestem jednak otwarty na dobre sugestie. Tymczasem wdrożyłemobejście hack poniżej i mam nadzieję na coś bardziej eleganckiego, a przynajmniej pozwala mi w jakiś sposób całkowicie usunąć FooBaseClass.

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