2012-02-20 6 views
9

Obecnie XmlSerializer produkuje następującą strukturę:XmlSerializer zastąpić XSI: typ do węzła nazwa

<config> 
    <BaseType xsi:type="DerivedType1" /> 
    <BaseType xsi:type="DerivedType2" /> 
</config> 

jest jakiś sposób, aby umieścić nazwę typu do węzła:

<config> 
    <DerivedType1 /> 
    <DerivedType2 /> 
</config> 

?

+0

można podać kod klasy chcesz serializacji? – Seb

Odpowiedz

0

Można po prostu zastąpić nazwę elementu za pomocą Atrybutu XmlElement np.

[XmlElement("DerivedType1")] 
public BaseType : DerivedType1 {get;set;} 

jeśli nadal będzie umieścić xsi: Wpisz w choć i generować jeszcze większe zamieszanie ...

Co robi twoja klasa wyglądać?

+0

Nie chcę zastępować nazwy elementu. Chcę, aby serializator ustawił nazwę równą nazwie klasy – SiberianGuy

+0

Tak właśnie zamierza zrobić ta odpowiedź. – Seb

+1

To zrobi. Z tego, co wiem, nie można stłumić pisania, ponieważ wtedy nigdy nie będzie możliwe deserialise. Jeśli nie potrzebujesz deserializacji, to nie serializujesz, dlatego powinieneś przestać się martwić serializacją i po prostu napisać metodę dumptoxml dla swojej klasy. Serializacja ma reguły, jeśli ich nie śledzisz, nie robisz tego ... –

24

Użyj przeciążenia konstruktora XmlElementAttribute(string elementName, Type type). Pozwala na zastąpienie nazwy elementu ze względu na faktyczny typ znaleziony w elemencie. Układaj kilka z nich razem, jeśli masz wiele typów pochodnych.

Jeśli próbujesz przekształcić do postaci szeregowej kolekcję ogólną, taką jak List<Base>, która może zawierać wystąpienia Derived, użyj XmlArrayItem w ten sam sposób.

Zdefiniowanie w ten sposób także niejawnie sprawia typ pochodzący znany, więc atrybutem XmlInclude nie jest wymagane

definicja próbki:

[XmlRoot] 
public class Data 
{ 
    [XmlElement("Derived1", typeof(Derived1))] 
    [XmlElement("Derived2", typeof(Derived2))] 
    public Base foo { get; set; } 
    [XmlArrayItem("Derived1", typeof(Derived1))] 
    [XmlArrayItem("Derived2", typeof(Derived2))] 
    public List<Base> fooList { get; set; } 
} 

public class Base { ... } 
public class Derived1 : Base { ... } 
public class Derived2 : Base { ... } 
0

Dlaczego ludzie ciągle mówią „nigdy nie będziesz w stanie deserializować. " To jest w zasadzie FALSE.

public class BaseClass { 
    public string Name {get;set;} 
} 
[XmlRoot("BaseClass")] 
public class ChildClass : BaseClass { 
    public int Value {get;set;} 
} 
[XmlRoot("BaseClass")] 
public class FlatClass 
{ 
    public string Name {get;set;} 
    public int Value {get;set;} 
} 

XmlSerializer ser1 = new XmlSerializer(typeof(BaseClass)); 
XmlSerializer ser2 = new XmlSerializer(typeof(ChildClass)); 
XmlSerializer ser3 = new XmlSerializer(typeof(FlatClass)); 
ser1.Serialize(File.Open("ser1.xml", FileMode.Create), new BaseClass(){Name="Base"}); 
ser2.Serialize(File.Open("ser2.xml", FileMode.Create), new ChildClass(){Name="Child",Value = 1}); 

ser1.Deserialize(File.OpenRead("ser2.xml")); 
ser2.Deserialize(File.OpenRead("ser1.xml")); 
ser3.Deserialize(File.OpenRead("ser2.xml")); 

Bum. Działa po prostu DOKŁADNIE !!!!! Serializacja idealnie pasuje do wszystkich trzech trybów. wynikowe obiekty mogą nie być w 100% po obu stronach, ale zmieniają się deserializująco. Ser1 ignoruje elementu Wartość gdy deserializacji ser2.xml Ser2 pomija propertuy wartość podczas deserializacji ser1.xml

Jedyną rzeczą, która łamie ten model jest:

ser1.Serailize(File.Open("ser3.xml", FileMode.Create), new ChildClass(){Name = "Child2", Value = 2}); 
XmlSerialize ser3 = new XmlSerializer(typeof(FlatClass)); 
ser3.Deserialize(File.OpenRead("ser3.xml")); 

tej ostatniej przerwy, ponieważ posiadał w tym serializer dla BaseClass jest zgodny ze standardem schematu (aczkolwiek wartościowy i 99% czasu trwania standardu), w tym atrybut xsi: type = "ChildClass" na elemencie. Ser3 nie może przetworzyć tego typu, ponieważ nie jest on realizowany dla tego typu, szczególnie jeśli FlatClass istnieje w innym złożeniu w sieci WAN lub LAN. Podobnie jak Honey-Badger XmlSerailizer NIE PAMIĘTAJ o elementach lub wartościach, dopóki może je znaleźć, a nic w schemacie nie przerywa procesu. Atrybut XSI: TYPE przerywa schemat.

Podobnie, na przykład, przy korzystaniu z WCF lub innych systemów opartych na komunikacji XML, jeśli Usługa ma klasę o nazwie FlatClass, NIE BĘDZIE DESERIALIZOWAĆ klasy ChildClass zawierającej atrybut xsi: type = "". Jeśli jednak nie korzystasz z serializera dla BaseClass, będzie deserializował dokładnie ten sam XML bez tego atrybutu xsi: type.

Q.E.D. Często jest to czasy korzystne, konieczne i DESIRABLE, do NOT obejmują atrybut xsi: type.

W związku z tym istnieje sposób na utworzenie XmlSerializer dla typu BaseClass i poinformowanie go, aby nie uwzględniał atrybutu xsi: type podczas serializowania typu potomnego?

Dzięki Jaeden "Sifo Dyas" al'Raec Ruiner