There was an error generating the XML document at Serialize method - c#

as this link , I have public property although this error There was an error generating the XML document occur at ser.Serialize(sw, this); in SaveToXML method.
I have this class as parent, it has one property too!
public class XMLCollection<T> where T: new ()
{
private XmlSerializer ser;
private List<T> m_InnerList= new List<T>();
public List<T> InnerList {
get
{ return m_InnerList; }
set
{ m_InnerList = value; }
}
public XMLCollection()
{
ser = new XmlSerializer(this.GetType(), new XmlRootAttribute(this.GetType().Name ));
}
/// <summary>
///
/// </summary>
/// <param name="path">path format: #"D:\FolderName"</param>
public void SaveToXML(string path)
{
try
{
using (StreamWriter sw = new StreamWriter(path+ "\\"+this.GetType().Name+".xml"))
{
ser.Serialize(sw, this);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message );
}
}
public void LoadFromXML(string FullPath)
{
try
{
if (File.Exists(FullPath))
{
using (StreamReader sr= new StreamReader(FullPath))
{
this.InnerList=((XMLCollection<T>) ser.Deserialize(sr)).InnerList ;
}
}
else
{
Console.WriteLine("File not exist....");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message );
}
}
}
CollectionList is derived from it:
public class CollectionList :XMLCollection<Moshakhase>, IList<Moshakhase>, IDisposable
{
public enum SortType
{
Name, ID
}
#region ctor
public CollectionList()
{
}
public CollectionList(Moshakhase item)
{
this.Add(item);
}
public CollectionList(params Moshakhase[] item)
{
InnerList.AddRange(item);
}
#endregion
public override string ToString()
{
string str = this.GetType().Name + ":\r\n";
foreach (Moshakhase item in this)
{
str += string.Format("\t{0}({1})\r\n", item.Name, item.Id);
}
return str;
}
#region Sort
public void sort(SortType type)
{
switch (type)
{
case SortType.Name:
InnerList.Sort();
break;
case SortType.ID:
InnerList.Sort(new IDCompare());
break;
default:
break;
}
}
class IDCompare : IComparer<Moshakhase>
{
public int Compare(Moshakhase x, Moshakhase y)
{
if (x.Id > y.Id)
{
return 1;
}
else if (x.Id < y.Id)
{
return -1;
}
return 0;
}
}
#endregion
#region Ilist
public int IndexOf(Moshakhase item)
{
return InnerList.IndexOf(item);
}
public void Insert(int index, Moshakhase item)
{
InnerList.Insert(index, item);
}
public void RemoveAt(int index)
{
InnerList.RemoveAt(index);
}
public Moshakhase this[int index]
{
get
{
return InnerList[index];
}
set
{
InnerList[index] = value;
}
}
public void Add(Moshakhase item)
{
InnerList.Add(item);
}
public void Clear()
{
InnerList.Clear();
}
public bool Contains(Moshakhase item)
{
return InnerList.Contains(item);
}
public void CopyTo(Moshakhase[] array, int arrayIndex)
{
InnerList.CopyTo(array,arrayIndex );
}
public int Count
{
get { return InnerList.Count ; }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public bool Remove(Moshakhase item)
{
return InnerList.Remove(item);
}
public IEnumerator<Moshakhase> GetEnumerator()
{
return InnerList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return InnerList.GetEnumerator();
}
#endregion
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
Users is derived from CollectionList :
public class Users : CollectionList
{
public Users()
{
}
public Users(ketabkhune.unique.User user): base(user)
{
}
public Users(params ketabkhune.unique.User[] user):base(user)
{
}
}
I use this code to check it:
Users uList = new Users(new User[] {new User(4,"Kamran"), new User(3,"Sara"), new User(5,"Bahar") });
uList.SaveToXML(#"F:\xml");

when I combined XMLCollection with CollectionList and define CollectionList as a generic class. that error disappeared..
Don't forget blank constructor
[Serializable()]
public class CollectionList<T> : IList<T>
{
private XmlSerializer ser;
private List<T> InnerList = new List<T>();
#region ctor
public CollectionList()
{
ser = new XmlSerializer(this.GetType());
}
public CollectionList(string CollectionName)
{
ser = new XmlSerializer(this.GetType(), new XmlRootAttribute(CollectionName ));
}
....

Change Your Code Where The Line Like Bellow :
ser.Serialize(sw, m_InnerList);

Related

System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'

I'm trying to implement https://learn.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern into my pet shop for a school project. However I keep running into this error. I already tried looking it up but most common solutions like .ToList(); or ToArray(); dont work.
My observer class:
namespace Weekopdracht_College1
{
class ObservableStore : IObservable<Animal>
{
private List<IObserver<Animal>> observers;
private List<Animal> animals;
public ObservableStore()
{
observers = new List<IObserver<Animal>>();
animals = new List<Animal>();
}
public IDisposable Subscribe(IObserver<Animal> observer)
{
if (! observers.Contains(observer))
{
observers.Add(observer);
foreach(var item in animals)
{
observer.OnNext(item);
}
}
return new Unsubscriber<Animal>(observers, observer);
}
public void AddAnimal(int id)
{
AddAnimal(id, String.Empty, 0, 0);
}
public void AddAnimal(int id, string type, double price, int stock)
{
var info = new Animal(id, type, price, stock);
if (stock > 0 && ! animals.Contains(info))
{
animals.Add(info);
foreach (var observer in observers)
{
observer.OnNext(info);
}
}
else if (stock == 0)
{
var animalsToRemove = new List<Animal>();
foreach(var animal in animals)
{
if(info.AnimalId == animal.AnimalId)
{
animalsToRemove.Add(animal);
foreach (var observer in observers)
{
observer.OnNext(info);
}
}
foreach (var animalToRemove in animalsToRemove)
{
animals.Remove(animalToRemove);
}
animalsToRemove.Clear();
}
}
}
public void LastAnimalBought()
{
foreach (var observer in observers)
{
observer.OnCompleted();
}
observers.Clear();
}
}
}
This part doens't work:
else if (stock == 0)
{
var animalsToRemove = new List<Animal>();
foreach(var animal in animals) <--- Error point
{
if(info.AnimalId == animal.AnimalId)
{
animalsToRemove.Add(animal);
foreach (var observer in observers)
{
observer.OnNext(info);
}
}
foreach (var animalToRemove in animalsToRemove)
{
animals.Remove(animalToRemove);
}
animalsToRemove.Clear();
}
}
Animal class:
public class Animal
{
private int id { get; set; }
private string type { get; set; }
private double price { get; set; }
private int stock { get; set; }
internal Animal(int id, string type, double price, int stock)
{
this.id = id;
this.type = type;
this.stock = stock;
this.price = price;
}
public int AnimalId
{
get { return this.id; }
}
public string AnimalType {
get { return this.type; }
}
public double AnimalStock
{
get { return this.stock; }
}
public double AnimalPrice {
get { return this.price; }
}
}
Display class:
namespace Weekopdracht_College1
{
class StockScreen : IObserver<Animal>
{
private string name;
private List<string> animalInfos = new List<string>();
private IDisposable cancellation;
private string fmt = "{0,-20} {1,5} {2, 3} {3,4}";
public StockScreen(string name)
{
if (String.IsNullOrEmpty(name))
{
throw new ArgumentNullException("The observer must be assigned a name.");
}
this.name = name;
}
public virtual void Subscribe(ObservableStore provider)
{
cancellation = provider.Subscribe(this);
}
public virtual void Unsubscribe()
{
cancellation.Dispose();
animalInfos.Clear();
}
public virtual void OnCompleted()
{
animalInfos.Clear();
}
public virtual void OnError(Exception e)
{
// no implementation
}
public virtual void OnNext(Animal info)
{
bool updated = false;
if (info.AnimalStock == 0)
{
var animalsToRemove = new List<string>();
string name = String.Format("{0,5}", info.AnimalId);
foreach(var animalInfo in animalInfos)
{
if (animalInfo.Substring(21, 5).Equals(name))
{
animalsToRemove.Add(animalInfo);
}
animalsToRemove.Clear();
}
}
else
{
string animalInfo = String.Format(fmt, info.AnimalId, info.AnimalType, info.AnimalPrice, info.AnimalStock);
if (! animalInfos.Contains(animalInfo))
{
animalInfos.Add(animalInfo);
updated = true;
}
}
if(updated)
{
animalInfos.Sort();
Console.WriteLine("Animal information from: {0}", this.name);
foreach (var animalInfo in animalInfos)
{
Console.WriteLine(animalInfo);
}
Console.WriteLine();
}
}
}
}
Move the loop over animalsToRemove outside the foreach loop over animals:
var animalsToRemove = new List<Animal>();
foreach(var animal in animals) <--- Error point
{
if(info.AnimalId == animal.AnimalId)
{
animalsToRemove.Add(animal);
foreach (var observer in observers)
{
observer.OnNext(info);
}
}
}
foreach (var animalToRemove in animalsToRemove)
{
animals.Remove(animalToRemove);
}
animalsToRemove.Clear();

How do you remove items from several list boxes by removing one item associated with them all?

I want to remove Server1 from it's listbox, i'd want it to remove all the other items in the other listboxes associated with it as well. ("Server-Domain1" and all the "Server1-Domain1-CSR's"). Is there a way to do this?
To "bind" these list boxes i just used:
domainListBox.Items.Add((serverListBox.SelectedItem) + "-" + (this.domainTextbox.Text));
and
csrListBox.Items.Add((domainListBox.SelectedItem) + ("-CSR-1"));
csrListBox.Items.Add((domainListBox.SelectedItem) + ("-CSR-2"));
csrListBox.Items.Add((domainListBox.SelectedItem) + ("-CSR-3"));
If you choose your server from servers listbox, you can remove associated items like this (lets pretend there is some remove button, you selecting domain from listbox and clicking on remove button):
private void removeBtn_Click(object sender, EventArgs e)
{
List<string> items = csrListBox.Items.Cast<string>().ToList();
foreach (string item in csrListBox.Items)
{
Regex regex = new Regex(#"^" + domainListBox.SelectedItem + #"\w*");
Match match = regex.Match(item);
if (match.Success)
{
items.Remove(item);
}
}
csrListBox.DataSource = items;
}
Hope it helps.
Create a class that encapsulates the Server and it's details such as Domains and Csrs. Create a list of Servers and bind it to the first List Box. Then bind the other two List Boxes to the currently selected item of the first List Box. The end result may look like this:
serverListBox.ItemSource = Servers;
domainListBox.ItemSource = (serverListBox.SelectedItem as Server).Domains;
csrListBox.ItemSource = (serverListBox.SelectedItem as Server).Csrs;
This enables you to set the different List Boxes data without writing a lot of code that could make it unmaintainable.
Well, seeing your code, you just have to do something like this when you remove your server:
string server = serverListBox.SelectedItem as string;
serverListBox.Remove(server);
for (int i = domainListBox.Items.Count -1; i >-1; i--)
{
if (domainListBox.Items[i].ToString().StartsWith(server))
{
string domain = domainListBox.Items[i].ToString();
domainListBox.Items.RemoveAt(i);
for (int j = csrListBox.Items.Count-1; j > -1; j--)
{
if (csrListBox.Items[j].ToString().StartsWith(domain))
{
csrListBox.Items.RemoveAt(j);
}
}
}
}
Edit I have tested it now, this should work
a better option would be using observable pattern as
public class ObservableObject<T> : IList, IListSource
{
protected BindingSource src = null;
List<ListControl> Subscribers;
ObservableCollection<T> Data = new ObservableCollection<T>();
public bool IsReadOnly
{
get
{
return false;
}
}
public bool IsFixedSize
{
get
{
return false;
}
}
public int Count
{
get
{
return Data.Count;
}
}
public object SyncRoot
{
get
{
throw new NotImplementedException();
}
}
public bool IsSynchronized
{
get
{
throw new NotImplementedException();
}
}
public bool ContainsListCollection
{
get
{
return true;
}
}
object IList.this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = (T)value;
}
}
public T this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
public ObservableObject()
{
Data.CollectionChanged += Domains_CollectionChanged;
Subscribers = new List<ListControl>();
src = new BindingSource();
src.DataSource = Data;
}
private void Domains_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
src.ResetBindings(false);
}
public virtual void Subscribe(ListBox ctrl)
{
this.Subscribers.Add(ctrl);
//ctrl.DataBindings.Add(new Binding("SelectedValue", src, "Name",
// true, DataSourceUpdateMode.Never));
ctrl.DataSource = src;
}
public int Add(object value)
{
Data.Add((T)value);
return Data.Count - 1;
}
public bool Contains(object value)
{
return Data.Contains((T)value);
}
public void Clear()
{
Data.Clear();
}
public int IndexOf(object value)
{
return Data.IndexOf((T)value);
}
public void Insert(int index, object value)
{
Data.Insert(index, (T)value);
}
public void Remove(object value)
{
Data.Remove((T)value);
}
public void RemoveAt(int index)
{
Data.RemoveAt(index);
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public IEnumerator GetEnumerator()
{
return Data.GetEnumerator();
}
public IList GetList()
{
return Data;
}
}
public class BaseModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get { return _name; }
set
{
this._name = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
public class CSR : BaseModel
{
public override string ToString()
{
return Name;
}
}
public class Domain : BaseModel
{
public ObservableObject<CSR> CSRs { get; set; }
public Domain()
{
CSRs = new ObservableObject<CSR>();
}
public override string ToString()
{
return Name;
}
}
public class Server : BaseModel
{
public ObservableObject<Domain> Domains { get; set; }
public Server()
{
Domains = new ObservableObject<Domain>();
}
public override string ToString()
{
return Name;
}
}
public class DataModel : BaseModel
{
public ObservableObject<Server> Servers
{
get; set;
}
public DataModel()
{
Servers = new ObservableObject<Server>();
}
public override string ToString()
{
return Name;
}
}
on Form
DataModel m = new DataModel();
public Form1()
{
...
m.Servers.Subscribe(listBox1);
}
private void listBox2_Click(object sender, EventArgs e)
{
if (listBox2.SelectedIndex >= 0)
{
m.Servers[listBox1.SelectedIndex].Domains[listBox2.SelectedIndex].CSRs.Subscribe(listBox3);
}
}
private void listBox1_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex >= 0)
{
m.Servers[listBox1.SelectedIndex].Domains.Subscribe(listBox2);
}
}
you dont have to write code to remove items from forms in this perspective.removing object from model would do

StackOverFlowError in instance of XmlSerializer

I don't know why I have Stackoverflow error when Child class call parent class constractor?!
first of all: sorry for my long code, because some of my friends request for it, so I put it for u!
public class XMLCollection<T>: IList<T> where T: new ()
{
private XmlSerializer ser;
private List<T> InnerList= new List<T>();
public XMLCollection()
{
ser = new XmlSerializer(this.GetType(), new XmlRootAttribute(this.GetType().Name ));
}
/// <summary>
///
/// </summary>
/// <param name="path">path format: #"D:\FolderName"</param>
public void SaveToXML(string path)
{
try
{
using (StreamWriter sw = new StreamWriter(path+ "\\"+this.GetType().Name))
{
ser.Serialize(sw, this);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message );
}
}
public void LoadFromXML(string FullPath)
{
try
{
if (File.Exists(FullPath))
{
using (StreamReader sr= new StreamReader(FullPath))
{
this.InnerList=((XMLCollection<T>) ser.Deserialize(sr)).InnerList ;
}
}
else
{
Console.WriteLine("File not exist....");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message );
}
}
#region Ilist
public int IndexOf(T item)
{
throw new NotImplementedException();
}
public void Insert(int index, T item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public T this[int index]
{
get
{
return InnerList[index];
}
set
{
InnerList[index] = value;
}
}
public void Add(T item)
{
InnerList.Add(item);
}
public void Clear()
{
InnerList.Clear();
}
public bool Contains(T item)
{
throw new NotImplementedException();
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { throw new NotImplementedException(); }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public bool Remove(T item)
{
throw new NotImplementedException();
}
public IEnumerator<T> GetEnumerator()
{
return InnerList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return InnerList.GetEnumerator();
}
#endregion
this is derived class:
public class Moshakhase :XMLCollection<Moshakhase>, IDisposable , IComparable<Moshakhase> , IEquatable<Moshakhase>
{
[XmlAttribute]
public int Id { get; set; }
[XmlAttribute]
public string Name { get; set; }
#region ctor
public Moshakhase()
{
}
public Moshakhase(int id, string name)
{
this.Id = id;
this.Name = name;
}
#endregion
public override string ToString()
{
return string.Format("{0}:\tId:{1}\tName:{2}",this.GetType().Name ,this.Id,this.Name);
}
#region dispose
public void Dispose()
{
GC.SuppressFinalize(this);
}
#endregion
#region IComparable
/// <summary>
/// براساس نام
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public int CompareTo(Moshakhase other)
{
return this.Name.CompareTo(other.Name);
}
#endregion
#region IEquatable
public bool Equals(Moshakhase other)
{
if (this.Id== other.Id)
{
return true;
}
return false;
}
#endregion
}
Thanks for your attention.
I don't know why I removed IList from XMLCollection<T> worked.
maybe because I has implemented IList in an other level of inheritance.
Note: In serializing it's important to implement blank constructor

Serialization on classes that implement IEnumerator

I have written a program which will serialize and de-serialize, it does this fine (I plan on implementing it on the subclasses once I get it properly working on one). However I have run into trouble when I decided I wanted to be able to iterate through the results using a Foreach.
After this didn't work I to find out had to implement the IEnumerator and IEnumerable interfaces and add the required methods to my class. So I have, and this does allow me to loop through my collections.
The problem starts when I try to combine the two things...
When serializing I originally got this error:
Inner:
{"The type ThereIsOnlyRules.Army was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}
I added [XmlInclude(typeof(Employee))] to my class to prevent this exception but now first two root elements are called <ArrayofAnyType><AnyType> instead of <ArmyListing><Army>. I can't figure out how to change them back [XmlRoot("whatever")] for some reason has no effect.
When deserializing I get this error {"There is an error in XML document (0, 0)."}
Inner: {"Root element is missing."}
I have searched - but it seems like this error can be generated in numerous different ways. I haven't found any solutions that apply to my code (as far as I could tell).
I'd much appreciate some information on the cause or solution to these problems I'm having!
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; }
}
}
}
Form
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;
}
}
}
I found remove the implementing of IEnumerator, IEnumerable, then you don't have to use XmlInclude.
The output xml is following which can be deserialized.
<?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>
Edit:
I guess if class implement IEnumerable and IEnumerator. XmlSerialer will use it to enumerate. object Current {} property caused the type is lost. so Anytype shows.
What I suggest is to implement IEnumerable, IEnumerator
Following is my test code:
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# - How to implement IEnumerator on a class

How to implement IEnumerator on this class so that I can use it in foreach loop.
public class Items
{
private Dictionary<string, Configuration> _items = new Dictionary<string, Configuration>();
public Configuration this[string element]
{
get
{
if (_items.ContainsKey(element))
{
return _items[element];
}
else
{
return null;
}
}
set
{
_items[element] = value;
}
}
}
In this example Configuration is a simple class with few properties.
Just an example to implement typesafe IEnumerable and not IEnumerator which you will be able to use in foreach loop.
public class Items : IEnumerable<Configuration>
{
private Dictionary<string, Configuration> _items = new Dictionary<string, Configuration>();
public void Add(string element, Configuration config) {
_items[element] = config;
}
public Configuration this[string element]
{
get
{
if (_items.ContainsKey(element))
{
return _items[element];
}
else
{
return null;
}
}
set
{
_items[element] = value;
}
}
public IEnumerator<Configuration> GetEnumerator()
{
return _items.Values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _items.Values.GetEnumerator();
}
}
Regards.
You should be able to implement IEnumerator like this:
public class Items : IEnumerator<KeyValuePair<string, Configuration>>
{
private Dictionary<string, Configuration> _items = new Dictionary<string, Configuration>();
public Configuration this[string element]
{
get
{
if (_items.ContainsKey(element))
{
return _items[element];
}
else
{
return null;
}
}
set
{
_items[element] = value;
}
}
int current;
public object Current
{
get { return _items.ElementAt(current); }
}
public bool MoveNext()
{
if (_items.Count == 0 || _items.Count <= current)
{
return false;
}
return true;
}
public void Reset()
{
current = 0;
}
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
KeyValuePair<string, Configuration> IEnumerator<KeyValuePair<string, Configuration>>.Current
{
get { return _items.ElementAt(current); }
}
public void Dispose()
{
//Dispose here
}
}
But as already noted you could also just implement IEnumerable.
You don't need to implement IEnumerable or any interface. In order to be able to use your class in a foreach, all that you need is to add an instance method to your class with the follwing signature:
IEnumerator GetEnumerator()

Categories