2017-10-17 21 views
4

XML 문자열 역 직렬화 할 수 없습니다 : 내가 뭘 아래 나는대로 역 직렬화하기 위해 노력하고있어 다음 XML은 다음하지만 오류 얻을 수있다

There was an error reflecting type 'System.Collections.Generic.List`1[MyApp.Models.Field]

이 내 코드

public class FieldList 
{ 
    [XmlArray("fields")] 
    [XmlArrayItem("field")] 
    List<Field> Fields { get; set; } 
} 

public class Field 
{ 
    [XmlAttribute("type")] 
    public string Type { get; set; } 

    [XmlAttribute("required")] 
    public bool Required { get; set; } 

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

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

    [XmlElement("option")] 
    [JsonProperty("values")] 
    public List<Option> Options { get; set; } 
} 

public class Option 
{ 
    [XmlAttribute("label")] 
    public string Label { get; set; } 

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

    [XmlAttribute("selected")] 
    public bool Selected { get; set; } 

    /// <remarks/> 
    [XmlIgnore()] 
    public bool SelectedSpecified { get; set; } 

    [XmlText] 
    public string Text { get; set; } 
} 

var xml = @"<?xml version=""1.0"" ?> 
    <form-template> 
    <fields> 
     <field type=""select"" required=""true"" label=""Cars"" name=""cars"" > 
      <option label=""Toyota"" value=""Toyota"" selected=""true"">Toyota</option> 
      <option label=""Nisan"" value=""Nisan"" >Nisan</option> 
     </field> 
    </fields> 
    </form-template>"; 


var serializer = new XmlSerializer(typeof(FieldList), new XmlRootAttribute("form-template")); 
var stringReader = new StringReader(xml); 
var xmlFields = (FieldList)serializer.Deserialize(stringReader); 

을 잘못된?

* UPDATE *

public List<Option> Options { get; set; } 

수정 오류로

public IEnumerable<Option> Options { get; set; } 

을 변경 아래의 코멘트를 같이

하지만 지금은 아무것도 직렬화되지 않습니다 - 변수 xmlFields가 비어 ??? 특정 노드에서 읽어야합니까, 아니면 중요하지 않아야합니까?

+0

은'InnerException'는 단서를 포함해야합니다. –

+0

@ManfredRadlwimmer가'IEnumerable

+0

다음 속성은 인터페이스이기 때문에 가장 좋은 추측입니다. 공개 IEnumerable

답변

2

코드를 살펴 보겠습니다.

new XmlRootAttribute("form-template")<form-template> 노드에 매핑됩니다.

public class Field<field 노드에 매핑됩니다.

그러나 아무것도 노드 <fields>에 매핑됩니다.

추가 다음 클래스 :

public class FieldList 
{ 
    [XmlArray("fields")] 
    [XmlArrayItem("field")] 
    public List<Field> Fields { get; set; } 
} 

그것은 작동합니다 :

var serializer = new XmlSerializer(typeof(FieldList), new XmlRootAttribute("form-template")); 
var stringReader = new StringReader(xml); 
var xmlFields = (FieldList)serializer.Deserialize(stringReader); 
또한

, 당신은 Option 클래스에 속성을 추가해야합니다

[XmlText] 
public string Text { get; set; } 

,

업데이트.

FieldList 클래스를 제거 할 수 있습니다. 그러나 xml 노드의 일부를 수동으로 건너 뛰어야합니다.

List<Field> xmlFields; 
var serializer = new XmlSerializer(typeof(List<Field>), new XmlRootAttribute("fields")); 

// You can read from a stream or from a StringReader instead of a file 
using (var xmlReader = XmlReader.Create("test.xml")) 
{ 
    // Skip <form-template> node 
    xmlReader.ReadToFollowing("fields"); 

    xmlFields = (List<Field>)serializer.Deserialize(xmlReader); 
} 

추가 XmlType 속성 클래스에 :

[XmlType("field")] 
public class Field 
+0

당신의 해결책에 따라 개정안을 만들었지 만'xmlFields'는 여전히 null입니까? – adam78

+0

거기에''노드에서 XML을 읽기 시작할 수있는 방법이있어서 기존 XML을 수정하지 않고'FieldList' 클래스를 제거 할 수 있습니까? – adam78

+0

@ adam78 - 업데이트를 참조하십시오. –

3

하는 XmlSerializer는

public IEnumerable<Option> Options { get; set; } 

당신의 루트 요소는 당신이 가지고있는 XML 구조와 일치하지 않는

public List<Option> Options { get; set; } 

에, 추상적 인 특성이 있으므로 아래와 같이 목록에 IEnumerable을 변경하십시오 직렬화 수 없습니다. 나는

var xml = "<?xml version=\"1.0\" ?>" + 
        " " + 
        " <Fields>" + 
        "  <Field Type=\"select\" Required=\"true\" Label=\"Cars\" Name=\"cars\" >" + 
        "   <option label=\"Toyota\" lalue=\"Toyota\" selected=\"true\">Toyota</option>" + 
        "   <option label=\"Nisan\" value=\"Nisan\" >Nisan</option>" + 
        "  </Field>" + 
        " </Fields>"; 

및 역 직렬화 코드

XmlSerializer serializer = new XmlSerializer(typeof(List<Field>), new XmlRootAttribute("Fields")); 

    var stringReader = new StringReader(xml); 
     List<Field> xmlFields = (List<Field>)serializer.Deserialize(stringReader); 

가 지금은 벌금을 직렬화 복원되고,로, 아래와 같이 XML을 편집했습니다.

enter image description here

+0

'List

+0

'Option' 클래스는'[Serializable]'속성으로 표시되어 있습니까? 매개 변수가없는 CTOR가 있습니까? – Moerwald

+0

@Moerwald -'XmlSerializer' 클래스는'Serializable' 속성을 사용하지 않습니다. –

1

당신은 어떤 당신의 XML을 직렬화 할 올바르게 클래스를 생성해야, 출력을 참조하십시오. 클립 보드에 이중 "큰 따옴표"없이 정확한 XML을 복사하고 Visual Studio의 솔루션에있는 cs 파일로 이동하십시오. 편집 -> 붙여 넣기 -> XML 붙여 넣기을 클릭하십시오. 그러면 cs 파일에서 변환을위한 클래스가 올바르게 생성됩니다. 그런 다음 개인 변수를 사용하는 대신 자동 구현 속성으로 변경하여 화면에서 혼란을 줄이십시오. 다음 클래스의 집합

는 자동 실행 속성 변화 특성을 수정 클래스

같은
XmlSerializer serializer = new XmlSerializer(typeof(FormTemplate)); 
      var xml = @"<?xml version=""1.0"" ?> 
    <form-template> 
    <fields> 
     <field type=""select"" required=""true"" label=""Cars"" name=""cars"" > 
      <option label=""Toyota"" value=""Toyota"" selected=""true"">Toyota</option> 
      <option label=""Nisan"" value=""Nisan"" >Nisan</option> 
     </field> 
    </fields> 
    </form-template>"; 
      var stringReader = new StringReader(xml); 
      var xmlFields = serializer.Deserialize(stringReader); 

자동 생성 된 세트를 직렬화.

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
[System.Xml.Serialization.XmlRootAttribute("form-template", Namespace = "", IsNullable = false)] 
public partial class FormTemplate 
{ 
    /// <remarks/> 
    public Fields fields { get; set; } 
} 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class Fields 
{ 
    /// <remarks/> 
    public SingleField field { get; set; } 
} 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class SingleField 
{ 
    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute("option")] 
    public Option[] option { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string type { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public bool required { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string label { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string name { get; set; } 
    } 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class Option 
{ 
    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string label { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string value { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public bool selected { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlIgnoreAttribute()] 
    public bool selectedSpecified { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlTextAttribute()] 
    public string Value { get; set; } 

}