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