2016-03-02 2 views
0

У меня есть следующий код:XML десериализации производных классов C#

[XmlRoot(ElementName = "Container")] 
public class Container { 
    [XmlArray("Items", IsNullable = false)] 
    [XmlArrayItem("Item")] 
    public List<BaseItem> Items { get; set; } = new List<BaseItem>(); 
} 


public class BaseItem { 
    [XmlAttribute("SomeField")] 
    public string SomeField {get;set;} 
} 


public class DerivedItem : BaseItem { 
    [XmlAttribute("OtherField")] 
    public string OtherField {get;set;} 
} 

Как десериализации:

<Container> 
    <Items> 
     <Item SomeField="Value"/> 
     <Item SomeField="Value" OtherField="OtherValue"/> 
    </Items> 
</Container> 

так, Элементы поля в объекте Контейнер может содержать BaseItem и DerivedItem объекты из XML выше?

+0

'XmlSerializer' определяет тип имени элемента. Было бы приемлемо иметь '' вместо этого? – dbc

+0

На самом деле это недопустимый XML - так что все ответы - дерьмо. Вы ДОЛЖНЫ разделить наследование по имени элемента по стандарту XML. Затем вы определяете несколько записей XmlArrayItem с именем и типом подкласса. ЭТО XML - то, что вы просите здесь, не имеет классов, основанных на xml, в соответствии с XML-спецификацией. – TomTom

+1

В качестве альтернативы, вы бы хотели иметь ''? Вы можете сделать это, добавив ['[XmlInclude (typeof (DerivedItem))]'] (https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlincludeattribute%28v=vs.110% 29.aspx). См. Также [Xsi: тип поддержки привязки атрибутов] (https://msdn.microsoft.com/en-us/library/ca1ks327%28v=vs.100%29.aspx). – dbc

ответ

0

Ну, вы не можете, потому что при десериализации XmlSerializer не определяется, когда использовать BaseItem или DerivedItem. Поэтому imho вы не должны использовать наследование здесь.

Теперь вам, возможно, нужно знать, указан ли OtherField или нет.

К счастью, это может сделать XmlSerializer. Для этого вам нужно добавить в класс, представляющий элемент, свойство bool OtherFieldSpecified, которое указывает, правильно ли указано OtherField ....

Вы должны использовать

// Define other methods and classes here 
[XmlRoot(ElementName = "Container")] 
public class Container { 
    [XmlArray("Items", IsNullable = false)] 
    [XmlArrayItem("Item")] 
    public List<DerivedItem> Items { get; set; } 

} 

public class DerivedItem 
{ 
    [XmlAttribute("SomeField")] 
    public string SomeField {get;set;} 

    [XmlAttribute("OtherField")] 
    public string OtherField {get;set;} 

    public bool OtherFieldSpecified {get;set;} 
} 

Так немного отрегулировать работая LINQPad мазня дал мне этот код:

void Main() 
{ 

var xml = @" 
<Container> 
<Items> 
     <Item SomeField=""Value""/> 
     <Item SomeField=""Value"" OtherField=""OtherValue""/> 
</Items> 
</Container> 
"; 

var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)); 

    var ser = new XmlSerializer(typeof(Container)); 

    var container = (Container) ser.Deserialize(stream); 

    container.Dump(); 
} 
+0

Ну, он МОЖЕТ - если он придерживается стандарта XML, которого нет в его данных samlple. Образцы данных не содержат каких-либо производных элементов в соответствии со спецификацией XML. Когда он спрашивает о XML-решении, ваше решение не работает. – TomTom

+0

Он хочет десериализовать данный XML ... Я дал ему рабочую, действительную версию для десериализации этого. – Dbuggy

+0

Нет, это не то, что он говорит. Вы полагаете, что он не контролирует ситуацию. ЕСЛИ он имеет - тогда это не решение производного класса. Смотрите, что произойдет, если вы посмотрите на схему XML? Ups, не работая с производными классами. – TomTom

0

Можем ли мы начать с вами не проводки правильный XML?

Элементы уникальны. Наследование (производные типы) ДОЛЖНО изменить имя элемента. Это стандарт XML, поскольку имя элемента - это то, как XML-схема определяет, какие элементы существуют.

YOU do that then, вы можете добавить несколько записей XmlArrayItem - есть вторая перегрузка, которая берет тип включенного элемента.

+0

На самом деле атрибут 'xsi: type =" DerivedItem "' также может использоваться для указания типа. См. Https://www.w3.org/TR/xmlschema-1/#xsi_type и [Xsi: тип поддержки привязки атрибутов] (https://msdn.microsoft.com/en-us/library/ca1ks327%28v=vs 0,100% 29.aspx). И в любом случае необработанный XML совершенно правдоподобен, просто, что желаемое сопоставление схемы не поддерживается сериализатором. – dbc

Смежные вопросы