2012-02-14 3 views
2

필자는 직렬화 및 비 직렬화 프로그램을 작성했습니다.이 기능은 제대로 수행됩니다 (제대로 작동하면 하위 클래스에서 구현할 계획). 그러나 Foreach을 사용하여 결과를 반복 할 수 있기를 원할 때 문제가 생겼습니다.IEnumerator를 구현하는 클래스의 직렬화

이 작업을 수행하지 못한 후에는 IEnumeratorIEnumerable 인터페이스를 구현하고 클래스에 필요한 메소드를 추가해야한다는 것을 알게되었습니다. 그래서 가지고 있고 내 컬렉션을 통해 반복 할 수 있습니다.

나는이 두 가지를 결합 할 때 문제가 시작 ...

내가 원래이 오류가있어 직렬화 :

내부 : {"The type ThereIsOnlyRules.Army was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}

내가 방지하기 위해 내 수업에 [XmlInclude(typeof(Employee))] 추가를 이 예외하지만 이제는 처음 두 개의 루트 요소는 <ArmyListing><Army> 대신 <ArrayofAnyType><AnyType>이라고합니다. 어떤 이유로 든 [XmlRoot("whatever")]을 다시 변경하는 방법을 알 수 없습니다. 역 직렬화 할 때

는이 오류 {"There is an error in XML document (0, 0)."} 내부 얻을 : 내가 검색 한 {"Root element is missing."}

을 -하지만이 오류가 여러 가지 방법으로 생성 할 수처럼 보인다. 내 코드에 적용 할 수있는 솔루션을 찾지 못했습니다 (내가 말할 수있는 한).

나는 이러한 문제에 대한 원인이나 해결책에 대한 정보를 많이 주셔서 감사합니다!

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml.Serialization; 
using System.Runtime.Serialization; 
using System.IO; 
using System.Collections; 

namespace ThereIsOnlyRules 
{ 
[XmlInclude(typeof(Army))] 
public class ArmyListing : IEnumerator, IEnumerable 
{ 

    // Fields 
    private List<Army> _army; 

    // Properties 
    [XmlArray("army-category")] 
    public List<Army> Army 
    { 
     get { return _army; } 
     set { _army = value; } 
    } 

    // Public Methods 
    public void SerializeToXML(ArmyListing armyListing) 
    { 
     try 
     { 
      //armyListing.army.Add(army); 

      XmlSerializer serializer = new XmlSerializer(typeof(ArmyListing)); 
      //XmlSerializer serializer = new XmlSerializer(typeof(ArmyListing), new Type[] { typeof(ArmyListing) }); 
      TextWriter textWriter = new StreamWriter(@"C:\Test\40k.xml"); 
      serializer.Serialize(textWriter, armyListing); 
      textWriter.Close(); 
     } 
     catch (Exception ex) { } 
    } 

    #region IEnumerator/IEnumerable req methods 
    [XmlIgnore] 
    private int position = -1; 
    //enumerator & ienumerable 
    public IEnumerator GetEnumerator() 
    { 
     return (IEnumerator)this; 
    } 

    //enumerator 
    public bool MoveNext() 
    { 
     position++; 
     return (position < Army.Count); 
    } 

    //ienumerable 
    public void Reset() 
    { 
     position = 0; 
    } 
    [XmlIgnore] 
    public object Current 
    { 
     get { return Army[position]; } 
    } 

    // Added to prevent Exception 
    // To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) 
    //at all levels of their inheritance hierarchy. ThereIsOnlyRules.ArmyListing does not implement Add(System.Object). 
    public void Add(Object fix) 
    { } 
    #endregion 
} 

[Serializable] 
public class Army// : IEnumerator, IEnumerable 
{ 
    // Fields 
    private List<UnitCategory> _unitCategory; 
    private string _armyName; 

    // Properties 
    [XmlArray("unit-category")] 
    public List<UnitCategory> UnitCategory 
    { 
     get { return _unitCategory; } 
     set { _unitCategory = value; } 
    } 

    [XmlAttribute("name")] 
    public string ArmyName 
    { 
     get { return _armyName; } 
     set { _armyName = value; } 
    } 

    //#region IEnumerator/IEnumerable req methods 
    //private int position = -1; 
    ////enumerator & ienumerable 
    //public IEnumerator GetEnumerator() 
    //{ 
    // return (IEnumerator)this; 
    //} 

    ////enumerator 
    //public bool MoveNext() 
    //{ 
    // position++; 
    // return (position < UnitCategory.Count); 
    //} 

    ////ienumerable 
    //public void Reset() 
    //{ 
    // position = 0; 
    //} 
    //public object Current 
    //{ 
    // get { return UnitCategory[position]; } 
    //} 
    //public void Add(Object Army) 
    //{ } 
    //#endregion 
} 

[Serializable] 
public class UnitCategory// : IEnumerator, IEnumerable 
{ 
    // Fields 
    private List<UnitType> _unitType; 
    private string _unitCategoryName; 

    // Properties 
    [XmlArray("unit-type")] 
    public List<UnitType> UnitType 
    { 
     get { return _unitType; } 
     set { _unitType = value; } 
    } 

    [XmlAttribute("name")] 
    public string UnitCategoryName 
    { 
     get { return _unitCategoryName; } 
     set { _unitCategoryName = value; } 
    } 

    //#region IEnumerator/IEnumerable req methods 
    //private int position = -1; 
    ////enumerator & ienumerable 
    //public IEnumerator GetEnumerator() 
    //{ 
    // return (IEnumerator)this; 
    //} 

    ////enumerator 
    //public bool MoveNext() 
    //{ 
    // position++; 
    // return (position < UnitType.Count); 
    //} 

    ////ienumerable 
    //public void Reset() 
    //{ 
    // position = 0; 
    //} 
    //public object Current 
    //{ 
    // get { return UnitType[position]; } 
    //} 
    //public void Add(Object Army) 
    //{ } 
    //#endregion 
} 

[Serializable] 
public class UnitType// : IEnumerator, IEnumerable 
{ 
    // Fields 
    private List<Unit> _unit; 
    private string _unitTypeName; 

    //Properties 
    [XmlArray("unit")] 
    public List<Unit> Unit 
    { 
     get { return _unit; } 
     set { _unit = value; } 
    } 

    [XmlAttribute("name")] 
    public string UnitTypeName 
    { 
     get { return _unitTypeName; } 
     set { _unitTypeName = value; } 
    } 

    //#region IEnumerator/IEnumerable req methods 
    //private int position = -1; 

    ////enumerator & ienumerable 
    //public IEnumerator GetEnumerator() 
    //{ 
    // return (IEnumerator)this; 
    //} 

    ////enumerator 
    //public bool MoveNext() 
    //{ 
    // position++; 
    // return (position < Unit.Count); 
    //} 

    ////ienumerable 
    //public void Reset() 
    //{ 
    // position = 0; 
    //} 
    //public object Current 
    //{ 
    // get { return Unit[position]; } 
    //} 

    //public void Add(Object Army) 
    //{ } 
    //#endregion 
} 

[Serializable] 
public class Unit 
{ 
    // Fields 
    private string _unitName; 
    private string _composition; 
    private string _weaponSkill; 
    private string _ballisticSkill; 
    private string _strength; 
    private string _initiative; 
    private string _toughness; 
    private string _wounds; 
    private string _attacks; 
    private string _leadership; 
    private string _savingThrow; 
    private string _specialRules; 
    private string _dedicatedTransport; 
    private string _options; 
    private string _armour; 
    private string _weapons; 

    // Properties 
    [XmlAttribute("name")] 
    public string UnitName 
    { 
     get { return _unitName; } 
     set { _unitName = value; } 
    } 

    [XmlAttribute("composition")] 
    public string Composition 
    { 
     get { return _composition; } 
     set { _composition = value; } 
    } 

    [XmlAttribute("weapon-skill")] 
    public string WeaponSkill 
    { 
     get { return _weaponSkill; } 
     set { _weaponSkill = value; } 
    } 

    [XmlAttribute("ballistic-skill")] 
    public string BallisticSkill 
    { 
     get { return _ballisticSkill; } 
     set { _ballisticSkill = value; } 
    } 

    [XmlAttribute("strength")] 
    public string Strength 
    { 
     get { return _strength; } 
     set { _strength = value; } 
    } 

    [XmlAttribute("toughness")] 
    public string Toughness 
    { 
     get { return _toughness; } 
     set { _toughness = value; } 
    } 

    [XmlAttribute("wounds")] 
    public string Wounds 
    { 
     get { return _wounds; } 
     set { _wounds = value; } 
    } 

    [XmlAttribute("initiative")] 
    public string Initiative 
    { 
     get { return _initiative; } 
     set { _initiative = value; } 
    } 

    [XmlAttribute("attacks")] 
    public string Attacks 
    { 
     get { return _attacks; } 
     set { _attacks = value; } 
    } 

    [XmlAttribute("leadership")] 
    public string Leadership 
    { 
     get { return _leadership; } 
     set { _leadership = value; } 
    } 

    [XmlAttribute("saving-throw")] 
    public string SaveThrow 
    { 
     get { return _savingThrow; } 
     set { _savingThrow = value; } 
    } 

    [XmlAttribute("armour")] 
    public string Armour 
    { 
     get { return _armour; } 
     set { _armour = value; } 
    } 

    [XmlAttribute("weapons")] 
    public string Weapons 
    { 
     get { return _weapons; } 
     set { _weapons = value; } 
    } 

    [XmlAttribute("special-rules")] 
    public string SpecialRules 
    { 
     get { return _specialRules; } 
     set { _specialRules = value; } 
    } 

    [XmlAttribute("dedicated-transport")] 
    public string DedicatedTransport 
    { 
     get { return _dedicatedTransport; } 
     set { _dedicatedTransport = value; } 
    } 

    [XmlAttribute("options")] 
    public string Options 
    { 
     get { return _options; } 
     set { _options = value; } 
    } 
} 
} 

양식

using System; 
using System.Windows.Forms; 
using System.Collections.Generic; 
using System.Xml.Serialization; 
using System.IO; 

namespace ThereIsOnlyRules 
{ 
public partial class Form1 : Form 
{ 
    ArmyListing armyListing; 
    ArmyListing XmlListing = new ArmyListing(); 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     SerializeArmyListings(); 
    } 

    public static void SerializeArmyListings() 
    { 
     UnitCategory troopsCategory = new UnitCategory 
     { 
      UnitCategoryName = "Troops", 
      UnitType = new List<UnitType> 
      { 
       new UnitType 
        { 
         UnitTypeName = "Infantry", 
         Unit = new List<Unit> 
          { 
           new Unit 
            { 
             Armour = "Chitin", 
             Attacks = "3", 
             BallisticSkill = "100", 
             Composition = "20", 
             DedicatedTransport = "No", 
             Initiative = "3", 
             Leadership = "5", 
             Options = "8", 
             SaveThrow = "6+", 
             SpecialRules = "None", 
             Strength = "3", 
             Toughness = "4", 
             UnitName = "Hornmagant", 
             Weapons = "Many", 
             WeaponSkill = "3", 
             Wounds = "1"            
            } 
          } 
        } 
      } 
     }; 

     Army army = new Army 
     { 
      ArmyName = "Tyranid", 
      UnitCategory = new List<UnitCategory> 
     { 
      troopsCategory 
     } 
     }; 

     ArmyListing armyListing = new ArmyListing 
     { 
      Army = new List<Army> 
      { 
       army 
      } 
     }; 

     armyListing.SerializeToXML(armyListing);// SerializeToXml(armyListing); 
    } 

    public ArmyListing DeserializeXml() 
    { 

     string path = @"C:\Test\40k.xml"; 

     XmlSerializer serializer = new XmlSerializer(typeof(ArmyListing)); 
     //XmlSerializer serializer = new XmlSerializer(typeof(ArmyListing), new Type[] { typeof(ArmyListing) }); 


     StreamReader reader = new StreamReader(path); 

     XmlListing = (ArmyListing)serializer.Deserialize(reader); 
     reader.Close(); 

     return XmlListing; 

    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     DeserializeXml(); 

     ////test 
     //foreach (var list in armyListing) 
     //{ 
     // listBox1.DataSource = list; 
     //} 

     int xmlcount = XmlListing.Army.Count; 
    } 

} 
} 
+0

가 편집을 찾아 보게하십시오 : I 제안 무엇

는 IEnumerable을 구현하는 것입니다, IEnumerator를 다음은 내 테스트 코드입니다. – findcaiyzh

답변

1

내가있는 IEnumerator의 구현을 제거 발견, IEnumerable을, 당신은 XmlInclude를 사용할 필요가 없습니다.

출력 XML은 비 직렬화 될 수 있습니다.

<?xml version="1.0" encoding="utf-8"?> 
<ArmyListing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <army-category> 
    <Army name="Tyranid"> 
     <unit-category> 
     <UnitCategory name="Troops"> 
      <unit-type> 
      <UnitType name="Infantry"> 
       <unit> 
       <Unit name="Hornmagant" composition="20" weapon-skill="3" ballistic-skill="100" strength="3" toughness="4" wounds="1" initiative="3" attacks="3" leadership="5" saving-throw="6+" armour="Chitin" weapons="Many" special-rules="None" dedicated-transport="No" options="8" /> 
       </unit> 
      </UnitType> 
      </unit-type> 
     </UnitCategory> 
     </unit-category> 
    </Army> 
    </army-category> 
</ArmyListing> 

편집 : 클래스는 IEnumerable과 IEnumerator를 구현하는 경우 는 것 같아요. XmlSerialer는이를 사용하여 열거합니다. object Current {} 속성으로 인해 유형이 손실되었습니다. Anytype이 보여줍니다. 내 대답의 일부 :

public class ArmyListing : IEnumerable<Army>, IEnumerator<Army> 
{ 

    // Fields 
    private List<Army> _army; 

    // Properties 
    [XmlArray("army-category")]   
    public List<Army> Army 
    { 
     get { return _army; } 
     set { _army = value; } 
    } 

    // Public Methods 
    public void SerializeToXML(ArmyListing armyListing) 
    { 
     try 
     { 
      //armyListing.army.Add(army); 

      XmlSerializer serializer = new XmlSerializer(typeof(ArmyListing)); 
      //XmlSerializer serializer = new XmlSerializer(typeof(ArmyListing), new Type[] { typeof(ArmyListing) }); 
      TextWriter textWriter = new StreamWriter(@"C:\Temp\40k.xml"); 
      serializer.Serialize(textWriter, armyListing); 
      textWriter.Close(); 
     } 
     catch (Exception ex) { } 
    } 

    #region IEnumerator/IEnumerable req methods 
    [XmlIgnore] 
    private int position = -1; 


    // Added to prevent Exception 
    // To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) 
    //at all levels of their inheritance hierarchy. ThereIsOnlyRules.ArmyListing does not implement Add(System.Object). 

    public void Add(Army fix) 
    { 
     if (_army == null) 
      _army = new List<Army>(); 

     _army.Add(fix); 
    } 
    #endregion    

    public IEnumerator<Army> GetEnumerator() 
    { 
     return this; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this; 
    } 

    [XmlIgnore] 
    public Army Current 
    { 
     get { return _army[position]; } 

    } 

    public void Dispose() 
    { 

    } 

    [XmlIgnore] 
    object IEnumerator.Current 
    { 
     get { return _army[position]; } 
    } 

    public bool MoveNext() 
    { 
     position++; 
     return (position < Army.Count); 
    } 

    public void Reset() 
    { 
     position = 0; 
    } 
} 
+0

직렬화가 작동하는 것을 확인할 수 있지만 deserialization이 시도 될 때 NullReferenceException이 발생합니다. 반환되는 객체는 채워지지 않고, 그 카운트는 0이며, 「Current」는 nullException를 Throw합니다. Current에 대한 XmlIgnore 태그를 기쁨없이 사용해 보았습니다. 여전히 바이올린이 있습니다. – Amicable

+0

메서드를 추가하는 것이 중요합니다. 내 수정 된 public void Add (Army fix) 구현을 참조하십시오. – findcaiyzh

+0

아, 제 잘못입니다. Add 메서드의 Type을 변경하고 변경을 구현했는지 확인했습니다. 모든 일! 많은 감사합니다 :) – Amicable

관련 문제