I'm trying to read a object from a XML doc with C# using the System.XML.
I created that doc with the same application, but when I try to read, I get "System.InvalidOperationException" in System.Xml.dll.
<?xml version="1.0"?>
<PKW xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Fahrzeug>
<Name>Testname</Name>
<Color>Rot</Color>
<Turen>5</Turen>
<Speed>80</Speed>
</Fahrzeug>
<Sitze>3</Sitze>
</PKW>
I try to read this XML with the following code...
System.Xml.Serialization.XmlSerializer reader = new System.Xml.Serialization.XmlSerializer(typeof(Fahrzeug.PKW));
System.IO.StreamReader file = new System.IO.StreamReader(#"Car.xml");
Auto = (Fahrzeug.PKW) reader.Deserialize(file);
file.Close();
Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XML_test
{
public class Fahrzeug
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string color;
public string Color
{
get { return color; }
set { color = value; }
}
private int türen;
public int Türen
{
get { return türen; }
set { türen = value; }
}
private double speed;
public double Speed
{
get { return speed; }
set { speed = value; }
}
public Fahrzeug(string name,string color,int türen,double speed)
{
this.color = color;
this.türen= türen;
this.speed = speed;
this.Name = name;
}
private void Output()
{
Console.WriteLine("Color:\t" + this.color);
Console.WriteLine("Türen:\t" + this.Türen);
Console.WriteLine("Speed:\t" + this.speed);
}
public class PKW
{
private Fahrzeug fahrzeug;
public Fahrzeug Fahrzeug
{
get { return fahrzeug; }
set { fahrzeug = value; }
}
public PKW()
{
}
private int sitze;
public int Sitze
{
get { return sitze; }
set { sitze = value; }
}
public PKW(Fahrzeug F, int sitze)
{
this.fahrzeug = F;
this.sitze = sitze;
}
public void Output()
{
Fahrzeug.Output();
Console.WriteLine("Color:\t" + this.sitze);
}
}
}
}
Think if you move the PKW class outside the Fahrzeug class (so it's not an inner class any more) it might work. My guess is that it's not resolving PKW in the xml correctly.
Related
i am building a dictionary WPF application where you write a word and than the application tells u in what language the word is and also gives you a description of the word. Using MVVM.
Here is how it looks:
I have problem with finding out how to get the language and the description of word from a text file and put them in the text box, i dont mean the binding, but the exact method of getting the info.
Here is my Model:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
namespace dictionary
{
public class dictionaryModel
{
private string word;
private string language;
private string description;
public string Word
{
get
{
return word;
}
set
{
word = value;
}
}
public string Language
{
get
{
return language;
}
set
{
language = value;
}
}
public string Description
{
get
{
return description;
}
set
{
description = value;
}
}
public dictionaryModel(string describedWord, string WordLanguage, string WordDescription)
{
this.word = describedWord;
this.language = WordLanguage;
this.description = WordDescription;
}
public dictionaryModel()
{ }
}
and here is my View Model, so far:
namespace dictionary
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Markup;
public class dictionaryViewModel : INotifyPropertyChanged
{
private ICommand _getAnswer;
private dictionaryModel m;
private string w;
private string retLanguage;
private string retDescription;
private bool _canExecute;
public dictionaryViewModel()
{
_canExecute = true;
}
public string retLang
{
get
{
return retLanguage;
}
set
{
retLanguage = value;
NotifyPropertyChanged();
}
}
public string retDescr
{
get
{
return retDescription;
}
set
{
retDescription = value;
NotifyPropertyChanged();
}
}
public string word
{
get
{
return w;
}
set
{
w = value;
NotifyPropertyChanged();
}
}
public dictionaryModel model
{
get
{
return m;
}
set
{
m = value;
NotifyPropertyChanged();
}
}
public ICommand getAnswer
{
get
{
return _getAnswer ?? (_getAnswer = new RelayCommand(() => getWholeAnswer(word), _canExecute));
}
}
public dictionaryViewModel(dictionaryModel model, string word, string retLang, string retDescr,
ICommand getAnswer)
{
m = model;
w = word;
retLang = retLanguage;
retDescr = retDescription;
_getAnswer = getAnswer;
}
public ObservableCollection<dictionaryModel> readTxtFile()
{
ObservableCollection<dictionaryModel> dictObj = new ObservableCollection<dictionaryModel>();
string word;
string language;
string description;
var file = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "dictionary.txt");
StreamReader read = new StreamReader(file);
string line;
string[] item;
while((line=read.ReadLine())!=null)
{
item = line.Split(';');
word = item[0];
language = item[1];
description = item[2];
dictionaryModel object1 = new dictionaryModel(word, language, description);
dictObj.Add(object1);
}
read.Close();
return dictObj;
}
public void getWholeAnswer(string w)
{
string descr, lang;
dictionaryModel obj = null;
ObservableCollection<dictionaryModel> rdF = readTxtFile();
try
{
foreach(dictionaryModel a in rdF)
{
if(w.Equals(a))
{
descr = retDescr;
lang = retLang;
obj = a;
}
obj.Language = retLang;
obj.Description = retDescription;
}
}catch(Exception e)
{
ExceptionInfo();
}
}
private void ExceptionInfo()
{
throw new NotImplementedException();
}
private void NotifyPropertyChanged()
{
throw new NotImplementedException();
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
The method is getWholeAnswer(). You see what i have tried, but no success. If you have any ideas, please help me out...
I think the problem is here:
if(w.Equals(a))
w is a string, while a is dictionaryModel, you are comparing two different kind of types without defining an equality logic.
Maybe you would replace that line with this?
if(string.Compare(w.Trim(), a.word, true) == 0)
string.Compare reference on MSDN
string.Trim reference on MSDN
i found my mistake, i am posting the solution of the method, it could be helpful to someone:
public void getWholeAnswer(string w)
{
dictionaryModel obj = null;
ObservableCollection<dictionaryModel> rdF = readTxtFile();
bool find = false;
try
{
foreach(dictionaryModel a in rdF)
{
if(w.Equals(a.Word))
{
obj = a;
retLang = a.Language;
retDescr = a.Description;
find = true;
break;
}
}
if(false == find)
{
AskTheQuestion();
}
}catch(Exception e)
{
AskTheQuestion();
}
}
I have the following classes in a serialization:
[XmlRoot()]
public class XmlExample
{
private NodeA_Elem _nodea;
[XmlElemnt("NodeA")]
public NodeA_Elem NodeA
{
get
{
return _nodea;
}
set
{
_nodea=value;
}
}
private NodeB_Elem _nodeb;
[XmlElemnt("NodeB")]
public NodeB_Elem NodeB
{
get
{
return _nodeb;
}
set
{
_nodeb=value;
}
}
private NodeC_Elem _nodec;
[XmlElemnt("NodeC")]
public NodeC_Elem NodeC
{
get
{
return _nodec;
}
set
{
_nodec=value;
}
}
public class NodeA_Elem
{
[XmlText()]
public string value{get;set;}
}
public class NodeB_Elem
{
[XmlText()]
public string value{get;set;}
}
public class NodeC_Elem
{
[XmlText()]
public string value{get;set;}
}
If the value property of any classes NodaA, NodeB or NodeC is null or empty I have the following result:
<XmlExample>
<NodeA/>
<NodeB/>
<NodeC/>
</XmlExample>
What I have to do to these nodes don't appear like empty nodes if I don't set the value property?
You can use ShouldSerialize* pattern, something like this:-
public bool ShouldSerializeNodeA() {
return NodeA != null;
}
Refer here :-
Conditional xml serialization
Update:
Make it non nullable:-
[XmlElement(IsNullable = false)]
Edit:
Earlier I mentioned :-
public bool ShouldSerializeNodeA() {
return NodeB != null;
}
My mistake, it should be like this:-
public bool ShouldSerializeNodeA() {
return NodeA != null;
}
You can also use a boolean property with the suffix xSpecified to indicate whether or not to serialize a property. This is used by Xml clients which consume xml which have a default value (e.g. as specified with default=xxx in an XSD):
public bool NodeASpecified
{
get { return _nodea != null && !String.IsNullOrEmpty(_nodea.value); }
}
Do not mark these Specified properties with any Xml attributes.
Not related, but hard coding the *Specified properties to true in a partial class is useful if you have consumed a web service which has a default and a minOccurs=0, which would otherwise not be sent at all to the service if the value was coincidentally the same as the default value.
I added up some comments and find a solution. I could use the ShouldSerialize pattern in my code. The resulting code is:
[XmlRoot()]
public class XmlExample
{
private NodeA_Elem _nodea;
[XmlElemnt("NodeA")]
public NodeA_Elem NodeA
{
get
{
return _nodea;
}
set
{
_nodea=value;
}
}
public bool ShouldSerializeNodeA()
{
return !String.IsNullOrEmpty(_nodea.value);
}
private NodeB_Elem _nodeb;
[XmlElemnt("NodeB")]
public NodeB_Elem NodeB
{
get
{
return _nodeb;
}
set
{
_nodeb=value;
}
}
public bool ShouldSerializeNodeB()
{
return !String.IsNullOrEmpty(_nodeb.value);
}
private NodeC_Elem _nodec;
[XmlElemnt("NodeC")]
public NodeC_Elem NodeC
{
get
{
return _nodec;
}
set
{
_nodec=value;
}
}
public bool ShouldSerializeNodeC()
{
return !String.IsNullOrEmpty(_nodec.value);
}
}
public class NodeA_Elem
{
[XmlText()]
public string value{get;set;}
}
public class NodeB_Elem
{
[XmlText()]
public string value{get;set;}
}
public class NodeC_Elem
{
[XmlText()]
public string value{get;set;}
}
Edit:
Here is the full code of my example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace Serialization_Example
{
class Program
{
static void Main(string[] args)
{
MyXmlDocument document = new MyXmlDocument();
document.MyExample.NodeA.value = "Value To Node A";
document.MyExample.NodeC.value = "Value To Node C";
document.WriteToXml(#"C:\Users\user_Name\Desktop\mydocument.xml");
}
}
[XmlRoot("xmlExample")]
public class XmlExample
{
private NodeA_Elem _nodea;
[XmlElement()]
public NodeA_Elem NodeA
{
get
{
return _nodea;
}
set
{
_nodea = value;
}
}
public bool ShouldSerializeNodeA()
{
return !String.IsNullOrEmpty(_nodea.value);
}
private NodeB_Elem _nodeb;
[XmlElement("NodeB")]
public NodeB_Elem NodeB
{
get
{
return _nodeb;
}
set
{
_nodeb = value;
}
}
public bool ShouldSerializeNodeB()
{
return !String.IsNullOrEmpty(_nodeb.value);
}
private NodeC_Elem _nodec;
[XmlElement("NodeC")]
public NodeC_Elem NodeC
{
get
{
return _nodec;
}
set
{
_nodec = value;
}
}
public bool ShouldSerializeNodeC()
{
return !String.IsNullOrEmpty(_nodec.value);
}
public XmlExample()
{
_nodea = new NodeA_Elem();
_nodeb = new NodeB_Elem();
_nodec = new NodeC_Elem();
}
}
public class NodeA_Elem
{
[XmlText()]
public string value { get; set; }
}
public class NodeB_Elem
{
[XmlText()]
public string value { get; set; }
}
public class NodeC_Elem
{
[XmlText()]
public string value { get; set; }
}
public class MyXmlDocument
{
private XmlExample _myexample;
public XmlExample MyExample
{
get
{
return _myexample;
}
set
{
_myexample = value;
}
}
public void WriteToXml(string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlExample));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = Encoding.Unicode;
StringWriter txtwriter = new StringWriter();
XmlWriter xmlwtr = XmlWriter.Create(txtwriter, settings);
serializer.Serialize(xmlwtr, MyExample);
StreamWriter writer = new StreamWriter(path);
writer.Write(txtwriter.ToString());
writer.Close();
}
public MyXmlDocument()
{
_myexample = new XmlExample();
}
}
}
If you compile it, you'll see that if I don't set the value for NodeB.value, it won't generate a empty node like was happening before.
I need help with this code. If you run the code you'll get in the last 7 lines (which is for...loop for Order object) Exercise.OrderItem.The problem is that I would like to access the OrderItem objects with for...loop but all I get are the last 7 lines representing OrderItem objects.How can I access them in for...loop so that I get the same as in foreach...loop? I think it has something to do with the indexer.Thank You.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace Exercise
{
interface IPricing
{
//read/write property
double Price
{
get;
set;
}
double Discount
{
get;
set;
}
}
public class Order:IPricing
{
private string name;
private double price;
private static int OrderNo;
//private ArrayList m_items = new ArrayList();
private ArrayList m_items;
//static constructor
static Order()
{
OrderNo = 0;
}
//default constructor
public Order()
{
name = null;
price = 0;
OrderNo++;
m_items = new ArrayList();
}
//constructor with parameters
public Order(string name, double price)
{
this.name = name;
this.price = price;
OrderNo++;
this.m_items = new ArrayList();
}
//copy constructor
public Order(Order order)
{
this.name = order.name;
this.price = order.price;
this.m_items = order.m_items;
}
public string Name
{
get { return name; }
set { name = value; }
}
public IEnumerable Items
{
get { return m_items; }
private set { }
}
public void AddItem(OrderItem orderItem)
{
orderItem.Order = name;
m_items.Add(orderItem);
}
public static Order operator +(Order o1, Order o2)
{
Order o3 = new Order(o1.name+", "+o2.name,o1.price+o2.price);
o3.m_items.AddRange(o1.m_items);
o3.m_items.AddRange(o2.m_items);
return o3;
}
//indexer
public object this[int index]
{
get
{
m_items[index] = this.m_items[index];
return m_items[index];
}
set { m_items[index] = value; }
}
public double ItemCount
{
get { return m_items.Count; }
private set{}
}
public virtual void Print()
{
Console.WriteLine("*********************Order No. {0}***********************", OrderNo);
Console.WriteLine("Details");
Console.WriteLine("Name: {0}", name);
Console.WriteLine("Price: {0}", price);
}
public double Price
{
get { return price - Discount; }
set { price = value; }
}
public virtual double Discount
{
get { return 0; }
set { ;}
}
public void PrintItems()
{
Console.WriteLine("Items in this order: ");
Console.WriteLine();
foreach(OrderItem itm in this.m_items)
{
Console.WriteLine("Item name: {0,4};\tPart of order: {1}", itm.Name, itm.Order);
}
}
}
public class OrderItem
{
private string m_name; //name of the item in order
private string m_order; //name of the order whose parts are items with names m_name
//default constructor
public OrderItem()
{
m_order = null;
}
//parameter constructor
public OrderItem(string name)
{
this.m_name = name;
this.m_order = null;
}
//copy constructor
public OrderItem(OrderItem orderItem)
{
this.m_name = orderItem.m_name;
this.m_order = orderItem.m_order;
}
//Name read/write property
public string Name
{
get { return m_name; }
set { m_name = value; }
}
//Order read/write property
public string Order
{
get { return m_order; }
set { m_order = value; }
}
}
public class MainProgram
{
static void Main(string[] args)
{
string order1 = "Desktop PC";
Order desktopPC = new Order(order1,25000);
desktopPC.AddItem(new OrderItem("pc mouse"));
desktopPC.AddItem(new OrderItem("keyboard"));
desktopPC.AddItem(new OrderItem("monitor"));
desktopPC.AddItem(new OrderItem("pc"));
desktopPC.Print();
desktopPC.PrintItems();
Console.WriteLine();
string order2 = "Notebook";
Order notebook = new Order(order2, 54000);
notebook.AddItem(new OrderItem("mouse"));
notebook.AddItem(new OrderItem("bag"));
notebook.AddItem(new OrderItem("notebook"));
notebook.Print();
notebook.PrintItems();
Console.WriteLine();
Order total = desktopPC + notebook;
total.Print();
total.PrintItems();
Console.WriteLine();
Console.WriteLine("Getting the items via for loop");
for (int k = 0; k < total.ItemCount; k++)
{
Console.WriteLine(total[k]);
}
Console.ReadKey();
}
}
}
for (int k = 0; k < total.ItemCount; k++)
{
var x = total[k] as OrderItem;
if (x == null) continue;
Console.WriteLine(x.Name);
Console.WriteLine(x.Order);
}
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;
}
}
Goal:
Display Encapsulate field from Player
Problem:
Want to display datamember_id, _name and _bust in class mainform only by using bindingList
Was it suppose to use syntax [] above the encapsulate field?
Class MainForm
dataGridViewPlayers.AutoGenerateColumns=true;
dataGridViewPlayers.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.Fill;
bindingSourcePlayers.Clear();
bindingSourcePlayers.DataSource = _myGameManager.Players;
Class GameManager:
public BindingList<Player> Players
{
get
{
for (int i = 0; i < _myPlayerGUI_list.Count; i++)
{
_player.Add(new Player(_myPlayerGUI_list[i].Player));
}
return _player;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CardGameClassLibrary;
namespace CardGameLib
{
public class Player
{
private int _id;
private string _name;
private Hand _myHand;
private int _win;
private int _lost;
private bool _madeMove = false;
private bool _bust = false;
public int Id
{
get { return _id; }
set { _id = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public Hand MyHand
{
get { return _myHand; }
set { _myHand = value; }
}
public int Win
{
get { return _win; }
set { _win = value; }
}
public int Lost
{
get { return _lost; }
set { _lost = value; }
}
public bool MadeMove
{
get { return _madeMove; }
set { _madeMove = value; }
}
public bool Bust
{
get { return _bust; }
set { _bust = value; }
}
public Player(int pId)
{
_id = pId;
_myHand = new Hand();
}
public Player(Player pPlayer)
{
_id = pPlayer.Id;
//_name = pPlayer.Name;
_name = "adsf";
}
public Player()
{
}
}
}
You can use Browsable() attribute to prevent specific properties from being shown in the DataGridView when usin BindingList.
Example: if you want to hide MadeMove:
[Browsable(false)]
public bool MadeMove
{
get { return _madeMove; }
set { _madeMove = value; }
}