Laden...

Generische Liste mit Events

Erstellt von dr4g0n76 vor 15 Jahren Letzter Beitrag vor 15 Jahren 3.278 Views
dr4g0n76 Themenstarter:in
2.921 Beiträge seit 2005
vor 15 Jahren
Generische Liste mit Events

Beschreibung:

Generische Liste mit Events
Diese Liste ermöglich z.B. auf das hinzufügen oder Löschen eines Elements mittels Events zu reagieren. Die Liste wurde getestet.

Ein List<string> kann dann Problemlos durch ein CCustomList<string> ersetzt werden.


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;


namespace ExtendedBaseTypes
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class NewItemEventArgs : EventArgs
    {
        #region Declarations
        private int m_nIndex = -1;
        private object m_oValue = null;
        #endregion Declarations

        #region Properties
        public int Index
        {
            get { return this.m_nIndex; }
            set { this.m_nIndex = value; }
        }

        public object Value
        {
            get { return this.m_oValue; }
            set { this.m_oValue = value; }
        }
        #endregion Properties

        #region Constructors
        public NewItemEventArgs(int _nIndex,object _oValue)
        {
            this.m_nIndex = _nIndex;
            this.m_oValue = _oValue;
        }
        #endregion Constructors
    }

    [Serializable]
    public class ItemEventArgs : EventArgs
    {
        #region Declarations
        private object m_oObject = null;
        private int m_nIndex = -1;
        #endregion Declarations

        #region Properties
        public object Item
        {
            get { return this.m_oObject; }
            set { this.m_oObject = value; }
        }

        public int Index
        {
            get { return this.m_nIndex; }
            set { this.m_nIndex = value; }
        }
        #endregion Properties

        #region Constructors
        public ItemEventArgs(object _oObject)
        {
            this.m_oObject = _oObject;
        }

        public ItemEventArgs(int _nIndex,object _oObject)
        {
            this.m_nIndex = _nIndex;
            this.m_oObject = _oObject;
        }

        public ItemEventArgs(int _nIndex)
        {
            this.m_nIndex = _nIndex;
            this.m_oObject = null;
        }
        #endregion Constructors
    }

	/// <summary>
	/// This custom list is needed to be informed about actual changes.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	[Serializable]
	public class CCustomList<T> : List<T>, ICloneable
	{
		#region Declarations
		public delegate void ItemAddEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemAddedEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemInsertedEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemsClearEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemsClearCompleteEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemSetEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemSetCompleteEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemValidateEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemInsertEventHandler(object sender, NewItemEventArgs e);

		public delegate void ItemRemoveEventHandler(object sender, ItemEventArgs e);
		public delegate void ItemRemoveCompleteEventHandler(object sender, ItemEventArgs e);

		public event ItemInsertedEventHandler m_ItemInsertedEventHandler;
		public event ItemsClearEventHandler m_ItemClearEventHandler;
		public event ItemsClearCompleteEventHandler m_ItemClearCompleteEventHandler;
		public event ItemSetEventHandler m_ItemSetEventHandler;
		public event ItemSetCompleteEventHandler m_ItemSetCompleteEventHandler;
		public event ItemValidateEventHandler m_ItemValidateEventHandler;
		public event ItemInsertEventHandler m_ItemInsertEventHandler;

		public event ItemRemoveEventHandler m_ItemRemoveEventHandler;
		public event ItemRemoveCompleteEventHandler m_ItemRemoveCompleteEventHandler;
		#endregion Declarations

		#region Constructors
		public CCustomList()
		{
		}
		#endregion Constructors

		/// <summary>
		/// Adds the specified item of type T
		/// </summary>
		/// <param name="_tItem">The _t item.</param>
		public new virtual void Add(T _tItem)
		{
			OnInsert(this.Count - 1, _tItem);
			this.List.Add(_tItem);
			OnInsertComplete(this.IndexOf(_tItem), _tItem);
		}

		public new void Clear()
		{
			OnClear();
			base.Clear();
			OnClearComplete();
		}
		/// <summary>
		/// Removes the specified item of type T
		/// </summary>
		/// <param name="_item">The _item.</param>
		public new virtual void Remove(T _item)
		{
			int _nIndex = this.IndexOf(_item);
			OnRemove(_nIndex, _item);
			this.List.Remove(_item);
			OnRemoveComplete(_nIndex, _item);
		}

		public new virtual void RemoveRange(int _nIndex, int _nCount)
		{
			base.RemoveRange(_nIndex, _nCount);
		}

		/// <summary>
		/// Gets the range.
		/// </summary>
		/// <param name="_nIndex">Index of the _n.</param>
		/// <param name="_nCount">The _n count.</param>
		/// <returns></returns>
		public new virtual List<T> GetRange(int _nIndex, int _nCount)
		{
			List<T> tempList = new List<T>();
			for (int i = _nIndex; i < this.Count; i++)
			{
				tempList.Add(this[i]);
			}
			return tempList;
		}

		/// <summary>
		/// Adds the range.
		/// </summary>
		/// <param name="aItem">A item.</param>
		public virtual void AddRange(T[] aItem)
		{
			for (int i = 0; i < aItem.Length; i++)
			{
				this.Add(aItem[i]);
			}
		}

		/// <summary>
		/// Returns index of Element of Type t
		/// </summary>
		/// <param name="_tT">The _t T.</param>
		/// <returns></returns>
		public new int IndexOf(T _tT)
		{
			return this.List.IndexOf(_tT);
		}

		/// <summary>
		/// Gets the <see cref="T"/> with the specified index _nIndex
		/// </summary>
		/// <value></value>
		public new virtual T this[int _nIndex]
		{
			get { return (T)this.List[_nIndex]; }
			set
			{
				OnSet(_nIndex, base[_nIndex], value);
				this.List[_nIndex] = value;
				OnSetComplete(_nIndex, base[_nIndex], value);
			}
		}

		/// <summary>
		/// Called when [insert complete].
		/// </summary>
		/// <param name="_nIndex">Index of the _n.</param>
		/// <param name="_oValue">The _o value.</param>
		protected virtual void OnInsertComplete(int _nIndex, object _oValue)
		{
			if (this.m_ItemInsertedEventHandler != null)
			{
				this.m_ItemInsertedEventHandler(this, new ItemEventArgs(_nIndex, _oValue));
			}
		}

		/// <summary>
		/// Ruft eine <see cref="T:System.Collections.IList"></see> mit der Liste der Elemente in der <see cref="T:System.Collections.CollectionBase"></see>-Instanz ab.
		/// </summary>
		/// <value></value>
		/// <returns>Eine <see cref="T:System.Collections.IList"></see>, die die <see cref="T:System.Collections.CollectionBase"></see>-Instanz selbst darstellt.</returns>
		public IList List
		{
			get
			{
				return this;
			}
		}

		/// <summary>
		/// Determines whether [contains] [the specified _o value].
		/// </summary>
		/// <param name="_oValue">The _o value.</param>
		/// <returns>
		/// 	<c>true</c> if [contains] [the specified _o value]; otherwise, <c>false</c>.
		/// </returns>
		public bool Contains(object _oValue)
		{
			return this.List.Contains(_oValue);
		}

		/// <summary>
		/// Called when [clear].
		/// </summary>
		protected virtual void OnClear()
		{
			if (this.m_ItemClearEventHandler != null)
			{
				this.m_ItemClearEventHandler(this, null);
			}
		}

		/// <summary>
		/// executes after clearing contents of <see cref="T:System.Collections.CollectionBase"></see>-Instanz additional userdefined processes.
		/// </summary>
		protected virtual void OnClearComplete()
		{
			if (this.m_ItemClearCompleteEventHandler != null)
			{
				this.m_ItemClearCompleteEventHandler(this, null);
			}
		}

		/// <summary>
		/// executes additional processes before inserting of a new element in <see cref="T:System.Collections.CollectionBase"></see>-instance.
		/// </summary>
		/// <param name="index">Der nullbasierte Index, an dem value eingefügt werden soll.</param>
		/// <param name="value">Der neue Wert des Elements an index.</param>
		protected virtual void OnInsert(int index, object value)
		{
			if (this.m_ItemInsertEventHandler != null)
			{
				this.m_ItemInsertEventHandler(this, new NewItemEventArgs(index, value));
			}
		}

		/// <summary>
		/// calls additional userdefined processes by inserting into in <see cref="T:System.Collections.CollectionBase"></see>-Instanz aus.
		/// </summary>
		/// <param name="index">Der nullbasierte Index, an dem sich value befindet.</param>
		/// <param name="value">Der Wert des Elements, das an index entfernt wird.</param>
		protected virtual void OnRemove(int index, object value)
		{
			if (this.m_ItemRemoveEventHandler != null)
			{
				this.m_ItemRemoveEventHandler(this, new ItemEventArgs(index, value));
			}
		}

		/// <summary>
		/// Führt zusätzliche benutzerdefinierte Prozesse nach dem Entfernen eines Elements aus der <see cref="T:System.Collections.CollectionBase"></see>-Instanz aus.
		/// </summary>
		/// <param name="index">Der nullbasierte Index, an dem sich value befindet.</param>
		/// <param name="value">Der Wert des Elements, das an index entfernt wird.</param>
		protected virtual void OnRemoveComplete(int index, object value)
		{
			if (this.m_ItemRemoveCompleteEventHandler != null)
			{
				this.m_ItemRemoveCompleteEventHandler(this, new ItemEventArgs(index, value));
			}
		}

		/// <summary>
		/// Führt zusätzliche benutzerdefinierte Prozesse vor dem Festlegen eines Werts in der <see cref="T:System.Collections.CollectionBase"></see>-Instanz aus.
		/// </summary>
		/// <param name="index">Der nullbasierte Index, an dem sich oldValue befindet.</param>
		/// <param name="oldValue">Der Wert, der durch newValue ersetzt werden soll.</param>
		/// <param name="newValue">Der neue Wert des Elements an index.</param>
		protected virtual void OnSet(int index, object oldValue, object newValue)
		{
			if (this.m_ItemSetEventHandler != null)
			{
				this.m_ItemSetEventHandler(this, new ItemEventArgs(index));
			}
		}

		/// <summary>
		/// Führt zusätzliche benutzerdefinierte Prozesse nach dem Festlegen eines Werts in der <see cref="T:System.Collections.CollectionBase"></see>-Instanz aus.
		/// </summary>
		/// <param name="index">Der nullbasierte Index, an dem sich oldValue befindet.</param>
		/// <param name="oldValue">Der Wert, der durch newValue ersetzt werden soll.</param>
		/// <param name="newValue">Der neue Wert des Elements an index.</param>
		protected virtual void OnSetComplete(int index, object oldValue, object newValue)
		{
			if (this.m_ItemSetCompleteEventHandler != null)
			{
				this.m_ItemSetCompleteEventHandler(this, new ItemEventArgs(index));
			}
		}

		/// <summary>
		/// Führt zusätzliche benutzerdefinierte Prozesse beim Prüfen der Gültigkeit eines Werts aus.
		/// </summary>
		/// <param name="value">Das Objekt, dessen Gültigkeit geprüft werden soll.</param>
		protected virtual void OnValidate(object value)
		{
			if (this.m_ItemValidateEventHandler != null)
			{
				this.m_ItemValidateEventHandler(this, new ItemEventArgs(value));
			}
		}

		/// <summary>
		/// Creates a new object, representing a copy of the actual instance.
		/// </summary>
		/// <returns>
		/// new object representing copy of actual instance.
		/// </returns>
		public object Clone()
		{
			CCustomList<T> aList = new CCustomList<T>();
			foreach (object obj in this)
			{
				if (obj is ICloneable)
				{
					aList.Add((T)((ICloneable)obj).Clone());
				}
			}
			return aList;
		}
	}
}


Schlagwörter: <Bitte Schlagwörter, unter denen das Snippet über die Suche gefunden werden soll, hier eintragen>

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

Gelöschter Account
vor 15 Jahren

Ein List<string> kann dann Problemlos durch ein CCustomList<string> ersetzt werden.

ich möchte darauf hinweisen, das man das lieber nciht machen sollte, da die schnittstellenimplementierungen von "ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable" fehlen und keine serialisierung möglich ist.

zusätzlich gibt es bereits einen .net 2.0 frameworkpendant zu dieser liste namens BindingList<T> und eine portierung von .net 3.x zu .net 2.0 der ObservableCollection

@dr4g0n76
zu den eventmechnismen und den ganzen delegaten möchte ich dir Guide to C# -> Styleguide -> Events empfehlen.

edit: noch etwas. warum machst du hier eine generische collection aber lässt diese validierungs und setmethoden one generischen anteil?

O
778 Beiträge seit 2007
vor 15 Jahren

Wenn man wirklich mal eine eigene Collection braucht (weil die zum Beispiel beim registrieren irgendwas machen können muss, oder in diesem Fall halt ein Event feuern), dann sollte man eigentlich sowieso immer von System.Collections.ObjectModel.Collection<T> ableiten, nie von List<T>. Ehrlich gesagt hätt' ich mir bei List<T> ein sealed gewünscht, aber naja.

Der Grund ist genau das, was Jack schon meinte, die Schnittstellenmember sind bei List<T> als nicht überschreibbar gekennzeichnet, weshalb die Aufrufe dann imernoch an die Basis und damit an den Zusatzfunktionen vorbei gehen (Die Schnittstellenimplementierung fehlt natürlich nicht, aber sie wird halt nur von der Basisklasse übernommen).