我已经编写了一个可以序列化和反序列化的程序,它做的很好(我计划在正确使用它后再在子类上实现它)。但是,当我决定要使用Foreach
遍历结果时遇到麻烦。
在这行不通之后,我发现必须实现IEnumerator
和IEnumerable
接口并将必需的方法添加到我的类中。所以我有,这确实允许我遍历我的收藏。
当我尝试将两件事结合在一起时,问题就开始了。
序列化时,我最初收到此错误:
内:{"The type ThereIsOnlyRules.Army was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}
我在类中添加了[XmlInclude(typeof(Employee))]
以防止出现此异常,但是现在前两个根元素称为<ArrayofAnyType><AnyType>
而不是<ArmyListing><Army>
。由于某种原因,我不知道如何将其更改回[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;
}
}
}
最佳答案
我发现删除了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会显示出来。
我建议是实现IEnumerable,IEnumerator
以下是我的测试代码:
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;
}
}
关于c# - 实现IEnumerator的类的序列化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9285863/