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;
}
}
Related
All the objects in our system inherit a base class which has got a property of type object.
I have tried adding protoignore attribute to all the properties of the base class as well but that doesn't seem to work as well.
class Program
{
static void Main(string[] args)
{
Vehicle vehicle = new Vehicle();
vehicle.BodyStyleDescription = "4x4";
vehicle.BodyStyleText = "Prestige Medium";
dynamic protobufModel = TypeModel.Create();
AddTypeToModel<Vehicle>(protobufModel);
using (MemoryStream compressed = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(compressed, CompressionMode.Compress, true))
{
protobufModel.Serialize(gzip, vehicle);
}
string str = Convert.ToBase64String(compressed.GetBuffer(), 0, Convert.ToInt32(compressed.Length));
}
}
public static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
{
var properties = typeof(T).GetProperties().Select(p => p.Name).OrderBy(name => name);
return typeModel.Add(typeof(T), true).Add(properties.ToArray());
}
}
Following is the hierarchy of the object
public interface IObjectBaseClass
{
[ProtoIgnore()]
object Parent { get; set; }
[ProtoIgnore()]
bool IsSaved { get; set; }
[ProtoIgnore()]
string XmlAtLoad { get; set; }
}
public class ObjectBaseClass : IObjectBaseClass
{
public ObjectBaseClass()
{
}
[ProtoIgnore()]
internal object _Parent;
[ProtoIgnore()]
internal bool _IsSaved;
[ProtoIgnore()]
internal string _XmlAtLoad;
[ProtoIgnore()]
public bool IsSaved
{
get { return _IsSaved; }
set { _IsSaved = value; }
}
[ProtoIgnore()]
public object Parent
{
get { return _Parent; }
set { _Parent = value; }
}
[ProtoIgnore()]
public string XmlAtLoad
{
get { return _XmlAtLoad; }
set { _XmlAtLoad = value; }
}
}
public class Vehicle : ObjectBaseClass
{
private string _BodyStyleText;
private string _BodyStyleDescription;
public string BodyStyleDescription
{
get { return _BodyStyleDescription; }
set { _BodyStyleDescription = value; }
}
public string BodyStyleText
{
get { return _BodyStyleText; }
set { _BodyStyleText = value; }
}
}
Your problem is that when you do typeModel.Add(typeof(T), true).Add(properties.ToArray()) you are adding all properties of T to the runtime type model, including those marked with ProtoIgnore. You can see this by calling the debugging method protobufModel.GetSchema(typeof(Vehicle)) which returns:
message Object {
}
message Vehicle {
optional string BodyStyleDescription = 1;
optional string BodyStyleText = 2;
optional bool IsSaved = 3;
optional Object Parent = 4;
optional string XmlAtLoad = 5;
}
To avoid adding properties marked with [ProtoIgnore], you could do:
public static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
{
var properties = typeof(T)
.GetProperties()
.Where(p => !p.GetCustomAttributes<ProtoIgnoreAttribute>().Any())
.Select(p => p.Name)
.OrderBy(name => name);
return typeModel.Add(typeof(T), true).Add(properties.ToArray());
}
Alternatively, since you are manually annotating some of your models with protobuf attributes anyway, you could mark the derived types with [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)], e.g.:
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Vehicle : ObjectBaseClass
{
private string _BodyStyleText;
private string _BodyStyleDescription;
public string BodyStyleDescription
{
get { return _BodyStyleDescription; }
set { _BodyStyleDescription = value; }
}
public string BodyStyleText
{
get { return _BodyStyleText; }
set { _BodyStyleText = value; }
}
}
Using either method, the schema for Vehicle becomes:
message Vehicle {
optional string BodyStyleDescription = 1;
optional string BodyStyleText = 2;
}
This is what you require.
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
I have created a list of my own type... (Classes for custom types at bottom of page)
List<gridRecord> lgr = new List<gridRecord>();
lgr = populatedList();
I validate each field in the List with the code bellow... (This works fine!)
foreach (gridRecord gr in lgr)
{
gr.Quantity.validate();
gr.Title.validate();
gr.Pages.validate();
dt.Rows.Add(gr.Title.Value.ToString(), gr.Quantity.Value.ToString(), gr.Pages.Value.ToString());
}
However I will be adding new gridFields to the gridRecord Class, and do not want to change the code that is validating.
so...I would like to be able to do something like this...
foreach (gridField gf in lgr)
{
gf.Validate();
}
grid Record Class...
class gridRecord : Validateit
{
//Constructor
public gridRecord()
{
Quantity = new quantityField();
Title = new titleField();
Pages = new pagesField();
}
private quantityField quantity;
private titleField title;
private pagesField pages;
public quantityField Quantity
{
get { return quantity; }
set { quantity = value; }
}
public titleField Title
{
get { return title; }
set { title = value; }
}
public pagesField Pages
{
get { return pages; }
set { pages = value; }
}
public override void Validate()
{
}
}
gridField Class...
class gridField : Validateit
{
public gridField()
{
Value = "---";
isValid = false;
message = "";
}
private string value;
protected bool isValid;
private string message;
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public bool IsValid
{
get { return isValid; }
set { isValid = value; }
}
public string Message
{
get { return message; }
set { message = value; }
}
public override void Validate()
{
}
}
do I need to use IEnumerable if so how?
Thanks
If you want code like this:
foreach (gridRecord gr in lgr)
{
gr.Validate();
}
It is a simple case of implementing what you need within that Validate method of gridRecord (BTW: That class should be named GridRecord - classes should start with an upper case character according to C# naming convention)
class gridRecord : Validateit
{
//.. snip
public override void Validate()
{
this.Quantity.Validate();
this.Title.Validate();
this.Pages.Validate();
}
}
If, however, you want to enumerate all the fields you can make each gridRecord implement IEnumerable<gridField> like this:
class gridRecord : Validateit, IEnumerable<gridField>
{
//.. snip
public IEnumerator<gridField> GetEnumerator()
{
yield return Quantity;
yield return Title;
yield return Pages;
}
public IEnumerator GetEnumerator()
{
return GetEnumerator(); // generic version
}
}
Then you can have code like this:
foreach (gridRecord gr in lgr) // enumerate each record
{
foreach(gridField gf in gr) // enumerate each field within each record
{
gf.Validate();
}
}
I have a customer object class:
public class customerObject
{
private string _address1;
private string _address2;
private string _address3;
private string _category;
private string _country;
private string _county;
private string _custcode;
private string _fullname;
private string _int_rep_hou;
private string _int_rep_key;
private double _lat;
private double _lng;
private string _postcode;
private string _rep_code;
private string _telephone;
public customerObject()
{
}
public string Address1
{
get { return _address1; }
set { _address1 = value; }
}
public string Address2
{
get
{
return _address2;
}
set { _address2 = value; }
}
public string Address3 { get { return _address3; } set { _address3 = value; } }
public string Category
{
get { return _category; }
set { _category = value; }
}
public string Country { get { return _country; } set { _country = value; } }
public string County { get { return _county; } set { _county = value; } }
public string Custcode
{
get { return _custcode; }
set { _custcode = value; }
}
public string Fullname
{
get { return _fullname; }
set { _fullname = value; }
}
public string Int_rep_hou
{
get { return _int_rep_hou; }
set { _int_rep_hou = value; }
}
public string Int_rep_key
{
get { return _int_rep_key; }
set { _int_rep_key = value; }
}
public double Lat { get { return _lat; } set { _lat = value; } }
public double Lng { get { return _lng; } set { _lng = value; } }
public string Postcode { get { return _postcode; } set { _postcode = value; } }
public string Rep_code
{
get { return _rep_code; }
set { Rep_code = value; }
}
public string Telephone { get { return _telephone; } set { _telephone = value; }
}
}
I have a CustomCollections class
public class CustomerCollection
{
public List<customerObject> Customers { get; set; }
}
My method that loops through dt rows and converts to a customer object
public List<Valueobjects.CustomerCollection> dolist(DataTable temptablename)
{
//Create Collection Object
Valueobjects.CustomerCollection Collection = new Valueobjects.CustomerCollection();
foreach (DataRow row in temptablename.Rows)
{
//Create Customer Object
Valueobjects.customerObject Customer = new Valueobjects.customerObject();
//set values of customer object
Customer.Rep_code = "";
Customer.Int_rep_key = "";
Customer.Int_rep_hou = "";
Customer.Fullname = row["Fullname"].ToString().Trim();
Customer.Custcode = row["Custcode"].ToString().Trim();
Customer.Category = row["Category"].ToString().Trim();
Customer.Address1 = row["Address1"].ToString().Trim();
Customer.Address2 = row["Address2"].ToString().Trim();
Customer.Address3 = row["Address3"].ToString().Trim();
Customer.Postcode = row["Postcode"].ToString().Trim();
Customer.Country = row["Country"].ToString().Trim();
Customer.Telephone = row["Telephone"].ToString().Trim();
Customer.Lat = Convert.ToDouble(row["Lat"]);
Customer.Lng = Convert.ToDouble(row["Lng"]);
Customer.County = row["County"].ToString().Trim();
//add to the collection (list)
Collection.Customers.Add(Customer);
}
temptablename = null;
return Collection;
}
However when I create a new Customer object and a new CustomerCollection object I am getting an error when adding the customer to the collection list.
Error:
Error 32 Cannot implicitly convert type
'Classes.Valueobjects.CustomerCollection' to
'System.Collections.Generic.List'
Your method is returning a List<CustomerCollection>:
public List<Valueobjects.CustomerCollection> dolist(DataTable temptablename)
{
//...
}
But the code is trying to return a CustomerCollection:
return Collection;
Just as the error says, these two types are different.
If a CustomerCollection is already a collection of customers, then semantically what is a List<Valueobjects.CustomerCollection>? A collection of collections? It seems like you're over-pluralizing your objects :)
There are two approaches here. Either return a CustomerCollection from the method:
public CustomerCollection dolist(DataTable temptablename)
{
//...
}
Or use a List<Customer> if you want to use generic lists as your collection containers:
public List<Customer> dolist(DataTable temptablename)
{
//...
var Collection = new List<Customer>();
//...
Collection.Add(Customer);
//...
return Collection;
}
Side note: You may want to stick to C# conventions for variable naming. As you can see from the code highlighting here on Stack Overflow, your variable names can easily be mistaken for classes/types, which can cause confusion when supporting the code.
Return a CustomerCollection instead of a List<Valueobjects.CustomerCollection>:
public Valueobjects.CustomerCollection Dolist(DataTable temptablename)
{
// ...
Your object has a list, it is not a list.
MSDN: Inheritance
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; }
}