/ Published in: C#
A class which wraps a parent list containing mixed object types, to provide smaller strongly typed sub-lists of objects. These sub-lists can be modified, which then modifies the parent list concurrently (without events being triggered). Supports the merging of other lists of the same type. Supports serialization. Supports parent list auto-instantiation.
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
/// <summary> /// A class which wraps a parent list containing mixed object types, to /// provide smaller strongly typed sub-lists of objects. /// These sub-lists can be modified, which then modifies the parent list /// concurrently (without events being triggered). /// <para>Class is serializable</para>. /// </summary> /// <typeparam name="L">Type of objects in the sub list</typeparam> /// <typeparam name="P">The type objects in the parent list /// (from which <typeparamref name="L"/> derives or implements) </typeparam> [Serializable] public sealed class SubList<L, P> : IList<L> { private List<P> _parentList; private List<L> _tempList; //memory holder (for enumeration) /// <summary> /// For deserializer only. Do not use this constructor. /// </summary> internal protected SubList() { } /// <summary> /// List Constructor /// </summary> /// <param name="parentList">Reference to a parent list which contains mixed objects derived from <typeparamref name="P"/></param> public SubList(ref List<P> parentList) { //construct the reference if a null value is passed if (parentList == null) this._parentList = parentList; } /// <summary> /// Create a shallow copy of this sublist to a list of type <typeparamref name="L"/> /// </summary> /// <returns>A strongly typed list copy of the the objects of type <typeparamref name="L"/></returns> public List<L> ShallowCopy() { this._parentList.ForEach(delegate(P item) { ret.Add((L)(object)item); }); return ret; } public L[] ToArray() { List<L> ret = this.ShallowCopy(); return ret.ToArray(); } public bool IsParentValid() { return (this._parentList != null); } public bool IsValid(L item) { } public void Merge(List<L> list) { list.ForEach(delegate(L item) { if (IsValid(item) && !this._parentList.Contains((P)(object)item)) this._parentList.Add((P)(object)item); }); } #region IList<L> Members public int IndexOf(L item) { if (IsValid(item)) return this._parentList.IndexOf((P)(object)item); return -1; } public void Insert(int index, L item) { if (IsValid(item)) this._parentList.Insert(index, (P)(object)item); } public void RemoveAt(int index) { this._parentList.RemoveAt(index); } public L this[int index] { get { P ret = this._parentList[index]; return (L)(object)ret; return default(L); } set { P set = default(P); if (index < this._parentList.Count) set = this._parentList[index]; this._parentList[index] = (P)(object)value; } } #endregion #region ICollection<L> Members public void Add(L item) { if (IsValid(item)) this._parentList.Add((P)(object)item); } public void Clear() { foreach (P item in this._parentList) this._parentList.Remove((P)(object)item); } public bool Contains(L item) { if (IsValid(item)) return this._parentList.Contains((P)(object)item); return false; } public void CopyTo(L[] array, int arrayIndex) { List<L> ret = this.ShallowCopy(); if (ret.Count > 0) ret.CopyTo(array, arrayIndex); } public int Count { get { int ret = 0; foreach (P item in this._parentList) ret++; return ret; } } bool ICollection<L>.IsReadOnly { get { return ((ICollection<P>)this._parentList).IsReadOnly; } } public bool Remove(L item) { if (IsValid(item)) return this._parentList.Remove((P)(object)item); return false; } #endregion #region IEnumerable<L> Members IEnumerator<L> IEnumerable<L>.GetEnumerator() { this._tempList = this.ShallowCopy(); return this._tempList.GetEnumerator(); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return this._parentList.GetEnumerator(); } #endregion } //example of how to implement serialization------------------------------------- [Serializable, DesignerCategory("code")] public abstract class Base { /// <summary> /// for deserializer only /// </summary> internal Base() { } } [Serializable, DesignerCategory("code")] [XmlType("IndexItemAdd")] public class Add : Base { /// <summary> /// for deserializer only /// </summary> internal Add() : base() { } } [Serializable, DesignerCategory("code")] [XmlType("IndexItemDelete")] public class Delete : Base { /// <summary> /// for deserializer only /// </summary> internal Delete() : base() { } } [Serializable()] [DesignerCategory("code")] [XmlType("IndexItem")] public class IndexItem { private List<Base> allItems; private SubList<Add, Base> indexItemAddFields; private SubList<Delete, Base> indexItemDeleteFields; [XmlElement("IndexItemAdd")] public SubList<Add, Base> Adds { get { return this.indexItemAddFields; } set { if (value != null && value.IsParentValid()) this.indexItemAddFields = value; else } } [XmlElement("IndexItemDelete")] public SubList<Delete, Base> Deletes { get { return this.indexItemDeleteFields; } set { if (value != null && value.IsParentValid()) this.indexItemDeleteFields = value; else } } [XmlIgnore] public List<Base> Items { get { return this.allItems; } } }