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();
Related
I have a IHasTag interface, a TaggableItem class that implements IHasTag and a TaggingManager class which I want to make it the only one responsible for setting or clearing the Tags but I've been struggling all day trying to implement but with no luck.
How can I make this possible?
public class TaggableItem : TaggingManager.IHasTag
{
public string Tag { get; } // read only
}
public class TaggingManager
{
public interface IHasTag
{
string Tag { get; }
}
private List<IHasTag> _taggedItems = new();
public void TagItem(IHasTag item, string tag)
{
item.Tag = tag; // not working
_taggedItems.Add(item);
}
public void ClearAllTags()
{
foreach (var item in _taggedItems)
{
item.Tag = "": // not working
}
_taggedItems.Clear();
}
}
EDIT
I followed Thomas' suggestion and this is what I end up doing. I know it's not perfect, though. Thank you all for your advices.
public interface ITaggable
{
string? Tag { get; }
}
public interface ISelectable
{
bool IsSelected { get; }
}
public interface IItem : ITaggable, ISelectable
{
}
public class Item : IItem
{
protected Item() { }
public bool IsSelected { get; set; }
public string Tag { get; set; } = string.Empty;
// 'Item' will be created here returning IItem.
// So, unless you 'cast' it, you can't set 'Tag' or 'IsSelected'.
public static IItem CreateItem() => new Item();
}
public class SelectionManager
{
protected List<object> _items = new();
public void Select(ISelectable item)
{
if (item is Item selectable)
{
selectable.IsSelected = true;
_items.Add(item);
}
}
public void Unselect(ISelectable item)
{
if (item is Item selectable)
{
selectable.IsSelected = false;
_items.Remove(item);
}
}
}
public class TaggingManager
{
private List<object> _items = new();
public void Tag(ITaggable item, string tag)
{
if (item is Item taggable)
{
taggable.Tag = tag;
_items.Add(item);
}
}
public void Untag(ITaggable item)
{
if (item is Item taggable)
{
taggable.Tag = string.Empty;
_items.Remove(item);
}
}
}
My suggestion would be to have two interfaces for two purposes: reading and writing.
public interface IHasTag // interface for reading. Maybe IReadTag
{
string Tag { get; }
}
public interface ITagChange // interface for writing. Maybe IWriteTag
{
string Tag { set; }
}
public class TaggableItem : IHasTag, ITagChange // implement both
{
public string Tag { get; set; }
}
// Tagging manager gets write access (ITagChange)
public class TaggingManager
{
private List<ITagChange> _taggedItems = new ();
public void TagItem(ITagChange item, string tag)
{
item.Tag = tag;
_taggedItems.Add(item);
}
public void ClearAllTags()
{
foreach (var item in _taggedItems)
{
item.Tag = "";
}
_taggedItems.Clear();
}
}
// Everyone else has read access only (IHasTag)
class SomeoneElse
{
private List<IHasTag> _taggedItems = new ();
public void DoSomething(IHasTag item)
{
_taggedItems.Add(item);
var tag = item.Tag; // do something with the tag
}
}
class Instantiation
{
public void Main()
{
TaggableItem x = new TaggableItem();
TaggingManager m = new TaggingManager();
m.TagItem(x, "name");
SomeoneElse s = new SomeoneElse();
s.DoSomething(x);
}
}
One possible option is to move the "getter" also to the TagManager. Then the manager is responsible for the tags. The object itself does not even need to know about the tags.
You still can restrict this by exchanging object with an interface.
public class TagManager
{
private Dictionary<object, string> _tagedItems = new Dictionary<object, string>();
public bool HasTag(object item)
{
return _tagedItems.ContainsKey(item);
}
public string GetTag(object item)
{
return _tagedItems[item];
}
public void SetTag(object item, string tag)
{
if(!HasTag(item))
{
_tagedItems.Add(item, tag);
}
else
{
_tagedItems[item] = tag;
}
}
}
I don't think that this is really a answer to the OP, but one possible solution for the underlying problem.
I have 3 interfaces.
public interface IItem
{
string Name { get; set; }
}
public interface IEquipable : IItem
{
void Equip();
}
public interface IConsumable : IItem
{
void Use();
}
IEquipable is implemented by the classes Helmet and Bow, and IConsumable is implemented by classes Potion and Food.
Then, I have a class with a property which contains a List of IItem, and proceed to add a few items of both IEquipable and IConsumable after instantiating it.
public class Character
{
public List<IItem> Items { get; private set; }
public Character()
{
this.Items = new List<IItem>();
}
public void AddItem(IItem item)
{
this.Items.Add(item);
}
}
Program.cs
...
Character char = new Character();
char.AddItem(new Potion());
char.AddItem(new Food());
char.AddItem(new Helmet());
char.AddItem(new Bow());
...
Is there a way I can get a List of all IEquipable members from the List of IItems, each AS IEquipable?
I want to do something like
...
List<IEquipable> equipmentList = //do something to char.Items and get all items of type IEquipable.
IEquipment equipment = equipmentList.First(...)
equipment.Equip();
...
I've tried using List<IEquipable> equipmentList = char.Items.OfType<IEquipable>().ToList() but the resulting list ends up empty.
I implemented (and fixed minor typos in) your code like this:
void Main()
{
Character character = new Character();
character.AddItem(new Potion());
character.AddItem(new Food());
character.AddItem(new Helmet());
character.AddItem(new Bow());
List<IEquipable> equipmentList = character.Items.OfType<IEquipable>().ToList();
}
public class Potion : IConsumable
{
public string Name { get; set; }
public void Use()
{
throw new NotImplementedException();
}
}
public class Food : IConsumable
{
public string Name { get; set; }
public void Use()
{
throw new NotImplementedException();
}
}
public class Helmet : IEquipable
{
public string Name { get; set; }
public void Equip()
{
throw new NotImplementedException();
}
}
public class Bow : IEquipable
{
public string Name { get; set; }
public void Equip()
{
throw new NotImplementedException();
}
}
public interface IItem
{
string Name { get; set; }
}
public interface IEquipable : IItem
{
void Equip();
}
public interface IConsumable : IItem
{
void Use();
}
public class Character
{
public List<IItem> Items { get; private set; }
public Character()
{
this.Items = new List<IItem>();
}
public void AddItem(IItem item)
{
this.Items.Add(item);
}
}
Your exact code (albeit char renamed to character) works perfectly fine. The equipmentList ends up with two elements. The issue you're seeing, i.e. "the resulting list ends up empty", is not reproducible with the code you've posted.
You can use the OfType method
Filters the elements of an IEnumerable based on a specified type.
Signature
public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
Usage
var equipable = Character.Items.OfType<IEquipable>();
Or encapsulate it as a method in the instance or an extension method if you like
So it does work like I wanted. My actual code just had another issue and I'm a dummy for not actually posting that. So here it is, for future reference.
using System.Collections.Generic;
using RolePlayGame.Library.Items.Backstage;
using System.Linq;
using System.Text;
using System;
namespace RolePlayGame.Library.Characters.Backstage
{
public class Inventory
{
public List<IItem> StoredItems { get; private set; }
public List<EquippedItem> Gear { get; private set; }
public Inventory()
{
this.StoredItems = new List<IItem>();
this.Gear = new List<EquippedItem>();
}
public bool HasItem(string name)
{
return this.StoredItems.Exists(item => item.Name == name);
}
public bool HasItem(IItem item)
{
return this.StoredItems.Contains(item);
}
public void RemoveItem(string name)
{
int firstIndex = this.StoredItems.FindIndex(item => item.Name == name);
if (firstIndex != -1)
{
this.StoredItems.RemoveAt(firstIndex);
}
}
public void RemoveItem(IItem item)
{
int firstIndex = this.StoredItems.IndexOf(item);
if (firstIndex != -1)
{
this.StoredItems.RemoveAt(firstIndex);
}
}
public void AddItem(IItem item, int quantity)
{
for (int i = 0; i < quantity; i++)
{
this.StoredItems.Add(item);
}
}
public void AddItem(IItem item)
{
this.StoredItems.Add(item);
}
public bool CheckEquipmentSlot(EquipmentSlot slot)
{
return this.Gear.Exists(item => item.UsedSlots.Contains(slot));
}
public bool HasEquipment(IEquipment equipment)
{
return this.Gear.Exists(item => item.Item == equipment);
}
public void AddEquipment(IEquipment equipment)
{
IEquipment alreadyEquipped;
foreach (EquipmentSlot slot in equipment.SlotsUsed)
{
if (this.Gear.Exists(item => item.UsedSlots.Contains(slot)))
{
alreadyEquipped = this.Gear.Find(item => item.UsedSlots.Contains(slot)).Item;
this.RemoveEquipment(slot);
this.StoredItems.Add(alreadyEquipped);
}
}
EquippedItem newEquipment = new EquippedItem(equipment);
this.Gear.Add(newEquipment);
}
public void RemoveEquipment(EquipmentSlot slot)
{
this.Gear.RemoveAll(equipment => equipment.UsedSlots.Contains(slot));
}
public int GetAttributeBonusTotal(AttributeType attribute)
{
int bonusTotal = 0;
foreach (IEquipment item in this.StoredItems.OfType<IEquipment>().ToList())
{
bonusTotal += item.GetAttributeBonus(attribute);
}
return bonusTotal;
}
public int GetCarryWeight()
{
int totalWeight = 0;
foreach (IItem item in StoredItems)
{
totalWeight += item.Weight;
}
return totalWeight;
}
public string GearToString()
{
StringBuilder builder = new StringBuilder();
builder.Append(" Equipped Gear:");
foreach (EquippedItem equipment in this.Gear)
{
builder.Append($"\n {equipment.Item.Name}");
}
return builder.ToString();
}
public string ItemsToString()
{
StringBuilder builder = new StringBuilder();
builder.Append(" Inventory:");
foreach (IItem item in this.StoredItems.Distinct())
{
builder.Append($"\n {item.Name} x {this.StoredItems.FindAll(value => value == item).Count()}");
}
return builder.ToString();
}
public int GetDefenseRateAgainstTypeTotal(DamageType againstType)
{
int rate = 0;
List<IOutfit> outfits = this.Gear.Select(value => value.Item).OfType<IOutfit>().ToList();
foreach (IOutfit item in outfits)
{
rate += item.GetDefenseRateAgainstType(againstType);
}
return rate;
}
}
}
One of the last lines has the problem (now fixed). List<IOutfit> outfits = this.Gear.Select(value => value.Item).OfType<IOutfit>().ToList(); used to be List<IOutfit> outfits = this.Gear.OfType<IOutfit>().ToList();. But Gear is of type List<EquippedItem>, and EquippedItem is not an implementation of IItem.
Here is EquippedItem.cs
using RolePlayGame.Library.Items.Backstage;
using System.Collections.Generic;
namespace RolePlayGame.Library
{
public class EquippedItem
{
public List<EquipmentSlot> UsedSlots { get; set; }
public IEquipment Item { get; set; }
public EquippedItem(IEquipment equipment)
{
this.Item = equipment;
this.UsedSlots = equipment.SlotsUsed;
}
}
}
I needed to select the Item property from the items inside Gear as another list before doing the type filtering with .OfType<IOutfit>(). That's where .Select(value => value.Item) enters the stage.
So that's that. I'll learn to post actual code for future questions.
This is the first time I am getting NZEC error. I don't understand this error, I just found that it stands for "Non Zero Exit Code". But what does this means. When we get this error. I am getting this error on one of online coding challenge websites and not in Visual Studio.
I am real need of help. Please check following code snippet where I am getting this error and please suggest what I am doing wrong.
using System;
using System.Collections.Generic;
using System.Linq;
namespace PractiseConsoleApplication
{
internal class Program
{
private static void Main(string[] args)
{
//Get input
var stringInput = Console.ReadLine();
var numberOfRooms = Convert.ToInt32(Console.ReadLine());
var endOfInput = Convert.ToInt32(Console.ReadLine());
var customers = stringInput.ToArray();
var hotel = new Hotel(numberOfRooms);
foreach (var customerName in customers)
{
hotel.CheckInCheckoutCustomer(customerName);
}
Console.WriteLine(Convert.ToString(hotel.CustomersLeftWithoutStayingInHotel.Count));
}
}
internal class Hotel
{
public bool IsRoomAvailable { get; private set; }
public List<HotelRoom> Rooms { get; private set; }
public List<char> CustomersLeftWithoutStayingInHotel { get; private set; }
private Hotel()
{
Rooms = new List<HotelRoom>();
CustomersLeftWithoutStayingInHotel = new List<char>();
}
public Hotel(int numberOfRooms)
: this()
{
for (int i = 1; i <= numberOfRooms; i++)
{
Rooms.Add(new HotelRoom(i));
}
}
public void CheckInCheckoutCustomer(char customer)
{
if (CustomersLeftWithoutStayingInHotel.Any(f => f == customer))
{
return;
}
var existingCustomer = Rooms.FirstOrDefault(f => f.IsRoomAllocatedToCustomer && f.CustomerName == customer);
//Already room allocated to this customer
if (existingCustomer != null)
{
//checkout him
existingCustomer.CustomerCheckout();
}
else
{
//Get empty rooms
var emptyRoom = Rooms.FirstOrDefault(f => f.IsRoomAllocatedToCustomer == false);
if (emptyRoom != null)
{
emptyRoom.AllocateRoomToCustomer(customer);
}
else
{
CustomersLeftWithoutStayingInHotel.Add(customer);
}
}
}
}
internal class HotelRoom
{
public int RoomNumber { get; private set; }
public char? CustomerName { get; private set; }
public HotelRoom(int roomNumber)
{
RoomNumber = roomNumber;
CustomerName = null;
}
public bool IsRoomAllocatedToCustomer
{
get
{
return CustomerName.HasValue;
}
}
public void AllocateRoomToCustomer(char customerDetails)
{
CustomerName = customerDetails;
}
public void CustomerCheckout()
{
CustomerName = null;
}
}
internal class Customer
{
public char CustomerName { get; private set; }
public Customer(char name)
{
CustomerName = name;
}
}
}
as Tony Hopkinson says in the comments, main should return an int.
place this statement in the end of main method:
return 0;
this will exit with zero code(thus the Non Zero Exit Code error)
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);
}
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);