Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Collections/3.3/ObservableKeyedCollectionBase.cs @ 2574

Last change on this file since 2574 was 2574, checked in by swagner, 15 years ago

Restructured interfaces and base classes (#819)

File size: 9.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections;
24using System.Collections.Generic;
25using System.Collections.ObjectModel;
26using System.Linq;
27using System.Text;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Collections {
31  [Serializable]
32  public abstract class ObservableKeyedCollectionBase<TKey, TItem> : IObservableKeyedCollection<TKey, TItem> {
33    [Storable]
34    private Dictionary<TKey, TItem> dict;
35
36    #region Properties
37    public int Count {
38      get { return dict.Count; }
39    }
40    public IEqualityComparer<TKey> Comparer {
41      get { return dict.Comparer; }
42    }
43    public bool IsReadOnly {
44      get { return ((ICollection<KeyValuePair<TKey, TItem>>)dict).IsReadOnly; }
45    }
46
47    public TItem this[TKey key] {
48      get {
49        return dict[key];
50      }
51    }
52    #endregion
53
54    #region Constructors
55    protected ObservableKeyedCollectionBase() {
56      dict = new Dictionary<TKey, TItem>();
57    }
58    protected ObservableKeyedCollectionBase(int capacity) {
59      dict = new Dictionary<TKey, TItem>(capacity);
60    }
61    protected ObservableKeyedCollectionBase(IEqualityComparer<TKey> comparer) {
62      dict = new Dictionary<TKey, TItem>(comparer);
63    }
64    protected ObservableKeyedCollectionBase(IEnumerable<TItem> collection) {
65      if (collection == null) throw new ArgumentNullException();
66      dict = new Dictionary<TKey, TItem>();
67      foreach (TItem item in collection)
68        AddItem(item);
69    }
70    protected ObservableKeyedCollectionBase(int capacity, IEqualityComparer<TKey> comparer) {
71      dict = new Dictionary<TKey, TItem>(capacity, comparer);
72    }
73    protected ObservableKeyedCollectionBase(IEnumerable<TItem> collection, IEqualityComparer<TKey> comparer) {
74      if (collection == null) throw new ArgumentNullException();
75      dict = new Dictionary<TKey, TItem>(comparer);
76      foreach (TItem item in collection)
77        AddItem(item);
78    }
79    #endregion
80
81    #region Destructors
82    ~ObservableKeyedCollectionBase() {
83      Dispose(false);
84    }
85    protected virtual void Dispose(bool disposing) {
86      if (disposing) {
87        Clear();
88      }
89    }
90    public void Dispose() {
91      Dispose(true);
92      GC.SuppressFinalize(this);
93    }
94    #endregion
95
96    protected abstract TKey GetKeyForItem(TItem item);
97    protected void UpdateItemKey(TItem item) {
98      if (item == null) throw new ArgumentNullException();
99      TKey oldKey = default(TKey);
100      bool oldKeyFound = false;
101      foreach (KeyValuePair<TKey, TItem> entry in dict) {
102        if (entry.Value.Equals(item)) {
103          oldKey = entry.Key;
104          oldKeyFound = true;
105          break;
106        }
107      }
108      if (!oldKeyFound) throw new ArgumentException("item not found");
109      dict.Remove(oldKey);
110      dict.Add(GetKeyForItem(item), item);
111      OnItemsReplaced(new TItem[] { item }, new TItem[] { item });
112    }
113
114    #region Access
115    public bool Contains(TKey key) {
116      return dict.ContainsKey(key);
117    }
118    public bool Contains(TItem item) {
119      return dict.ContainsValue(item);
120    }
121
122    public bool TryGetValue(TKey key, out TItem item) {
123      return dict.TryGetValue(key, out item);
124    }
125
126    public bool Exists(Predicate<TItem> match) {
127      if (match == null) throw new ArgumentNullException();
128      foreach (TItem item in dict.Values) {
129        if (match(item)) return true;
130      }
131      return false;
132    }
133
134    public TItem Find(Predicate<TItem> match) {
135      if (match == null) throw new ArgumentNullException();
136      foreach (TItem item in dict.Values) {
137        if (match(item)) return item;
138      }
139      return default(TItem);
140    }
141    public ICollection<TItem> FindAll(Predicate<TItem> match) {
142      if (match == null) throw new ArgumentNullException();
143      List<TItem> result = new List<TItem>();
144      foreach (TItem item in dict.Values) {
145        if (match(item)) result.Add(item);
146      }
147      return result;
148    }
149    #endregion
150
151    #region Manipulation
152    protected virtual void AddItem(TItem item) {
153      dict.Add(GetKeyForItem(item), item);
154    }
155    public void Add(TItem item) {
156      AddItem(item);
157      OnItemsAdded(new TItem[] { item });
158    }
159    public void AddRange(IEnumerable<TItem> collection) {
160      if (collection == null) throw new ArgumentNullException();
161      foreach (TItem item in collection)
162        AddItem(item);
163      OnItemsAdded(collection);
164    }
165
166    protected virtual bool RemoveItem(TItem item) {
167      return dict.Remove(GetKeyForItem(item));
168    }
169    public bool Remove(TKey key) {
170      TItem item;
171      if (TryGetValue(key, out item)) {
172        RemoveItem(item);
173        OnItemsRemoved(new TItem[] { item });
174        return true;
175      }
176      return false;
177    }
178    public bool Remove(TItem item) {
179      if (RemoveItem(item)) {
180        OnItemsRemoved(new TItem[] { item });
181        return true;
182      }
183      return false;
184    }
185    public void RemoveRange(IEnumerable<TItem> collection) {
186      if (collection == null) throw new ArgumentNullException();
187      List<TItem> items = new List<TItem>();
188      foreach (TItem item in collection) {
189        if (RemoveItem(item))
190          items.Add(item);
191      }
192      if (items.Count > 0)
193        OnItemsRemoved(items);
194    }
195    public int RemoveAll(Predicate<TItem> match) {
196      ICollection<TItem> items = FindAll(match);
197      RemoveRange(items);
198      return items.Count;
199    }
200
201    protected virtual void ClearItems() {
202      dict.Clear();
203    }
204    public void Clear() {
205      TItem[] items = dict.Values.ToArray();
206      ClearItems();
207      OnCollectionReset(new TItem[0], items);
208    }
209    #endregion
210
211    #region Conversion
212    public TItem[] ToArray() {
213      return dict.Values.ToArray();
214    }
215    public void CopyTo(TItem[] array, int arrayIndex) {
216      dict.Values.CopyTo(array, arrayIndex);
217    }
218    public ICollection<TOutput> ConvertAll<TOutput>(Converter<TItem, TOutput> converter) {
219      if (converter == null) throw new ArgumentNullException();
220      List<TOutput> result = new List<TOutput>();
221      foreach (TItem item in dict.Values)
222        result.Add(converter(item));
223      return result;
224    }
225    #endregion
226
227    #region Processing
228    public void ForEach(Action<TItem> action) {
229      if (action == null) throw new ArgumentNullException();
230      foreach (TItem item in dict.Values)
231        action(item);
232    }
233    public bool TrueForAll(Predicate<TItem> match) {
234      if (match == null) throw new ArgumentNullException();
235      foreach (TItem item in dict.Values)
236        if (! match(item)) return false;
237      return true;
238    }
239    #endregion
240
241    #region Enumeration
242    public IEnumerator<TItem> GetEnumerator() {
243      return dict.Values.GetEnumerator();
244    }
245    IEnumerator IEnumerable.GetEnumerator() {
246      return dict.Values.GetEnumerator();
247    }
248    #endregion
249
250    #region Events
251    [field: NonSerialized]
252    public event CollectionItemsChangedEventHandler<TItem> ItemsAdded;
253    protected virtual void OnItemsAdded(IEnumerable<TItem> items) {
254      if (ItemsAdded != null)
255        ItemsAdded(this, new CollectionItemsChangedEventArgs<TItem>(items));
256    }
257
258    [field: NonSerialized]
259    public event CollectionItemsChangedEventHandler<TItem> ItemsRemoved;
260    protected virtual void OnItemsRemoved(IEnumerable<TItem> items) {
261      if (ItemsRemoved != null)
262        ItemsRemoved(this, new CollectionItemsChangedEventArgs<TItem>(items));
263    }
264
265    [field: NonSerialized]
266    public event CollectionItemsChangedEventHandler<TItem> ItemsReplaced;
267    protected virtual void OnItemsReplaced(IEnumerable<TItem> items, IEnumerable<TItem> oldItems) {
268      if (ItemsReplaced != null)
269        ItemsReplaced(this, new CollectionItemsChangedEventArgs<TItem>(items, oldItems));
270    }
271
272    [field: NonSerialized]
273    public event CollectionItemsChangedEventHandler<TItem> CollectionReset;
274    protected virtual void OnCollectionReset(IEnumerable<TItem> items, IEnumerable<TItem> oldItems) {
275      if (CollectionReset != null)
276        CollectionReset(this, new CollectionItemsChangedEventArgs<TItem>(items, oldItems));
277    }
278    #endregion
279  }
280}
Note: See TracBrowser for help on using the repository browser.