wasSharp – Blame information for rev 39
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
22 | office | 1 | /////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // |
||
3 | // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // |
||
4 | // rights of fair usage, the disclaimer and warranty conditions. // |
||
5 | /////////////////////////////////////////////////////////////////////////// |
||
6 | |||
7 | using System.Collections; |
||
8 | using System.Collections.Generic; |
||
9 | using System.Collections.Specialized; |
||
39 | office | 10 | using System.Threading; |
22 | office | 11 | |
12 | namespace wasSharp.Collections.Specialized |
||
13 | { |
||
14 | /////////////////////////////////////////////////////////////////////////// |
||
15 | // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // |
||
16 | /////////////////////////////////////////////////////////////////////////// |
||
17 | /// <summary> |
||
18 | /// An implementation of an observable Dictionary. |
||
19 | /// </summary> |
||
20 | /// <typeparam name="K">the key type</typeparam> |
||
21 | /// <typeparam name="V">the value type</typeparam> |
||
22 | public class ObservableDictionary<K, V> : IDictionary<K, V>, INotifyCollectionChanged |
||
23 | { |
||
39 | office | 24 | private readonly ReaderWriterLockSlim SyncRoot = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); |
22 | office | 25 | private readonly Dictionary<K, V> store = new Dictionary<K, V>(); |
26 | |||
27 | public bool IsVirgin { get; private set; } = true; |
||
28 | |||
29 | public V this[K key] |
||
30 | { |
||
39 | office | 31 | get |
32 | { |
||
33 | SyncRoot.EnterReadLock(); |
||
34 | var v = store[key]; |
||
35 | SyncRoot.ExitReadLock(); |
||
36 | return v; |
||
37 | } |
||
22 | office | 38 | |
39 | office | 39 | set |
40 | { |
||
41 | SyncRoot.EnterWriteLock(); |
||
42 | store[key] = value; |
||
43 | SyncRoot.ExitWriteLock(); |
||
44 | } |
||
22 | office | 45 | } |
46 | |||
47 | public int Count => store.Count; |
||
48 | |||
49 | public bool IsReadOnly => false; |
||
50 | |||
39 | office | 51 | public ICollection<K> Keys |
52 | { |
||
53 | get |
||
54 | { |
||
55 | SyncRoot.EnterReadLock(); |
||
56 | var v = store.Keys; |
||
57 | SyncRoot.ExitReadLock(); |
||
58 | return v; |
||
59 | } |
||
60 | } |
||
22 | office | 61 | |
39 | office | 62 | public ICollection<V> Values |
63 | { |
||
64 | get |
||
65 | { |
||
66 | SyncRoot.EnterReadLock(); |
||
67 | var v = store.Values; |
||
68 | SyncRoot.ExitReadLock(); |
||
69 | return v; |
||
70 | } |
||
71 | } |
||
22 | office | 72 | |
73 | public void Add(KeyValuePair<K, V> item) |
||
74 | { |
||
39 | office | 75 | SyncRoot.EnterWriteLock(); |
27 | office | 76 | ((IDictionary<K, V>)store).Add(item); |
39 | office | 77 | SyncRoot.ExitWriteLock(); |
22 | office | 78 | IsVirgin = false; |
79 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); |
||
80 | } |
||
81 | |||
82 | public void Add(K key, V value) |
||
83 | { |
||
39 | office | 84 | SyncRoot.EnterWriteLock(); |
22 | office | 85 | store.Add(key, value); |
39 | office | 86 | SyncRoot.ExitWriteLock(); |
22 | office | 87 | IsVirgin = false; |
88 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, |
||
89 | new KeyValuePair<K, V>(key, value))); |
||
90 | } |
||
91 | |||
92 | public void Clear() |
||
93 | { |
||
39 | office | 94 | SyncRoot.EnterWriteLock(); |
22 | office | 95 | store.Clear(); |
39 | office | 96 | SyncRoot.ExitWriteLock(); |
22 | office | 97 | if (!IsVirgin) |
98 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); |
||
99 | IsVirgin = false; |
||
100 | } |
||
101 | |||
102 | public bool Contains(KeyValuePair<K, V> item) |
||
103 | { |
||
39 | office | 104 | SyncRoot.EnterReadLock(); |
105 | var c = ((IDictionary<K, V>)store).Contains(item); |
||
106 | SyncRoot.ExitReadLock(); |
||
107 | return c; |
||
22 | office | 108 | } |
109 | |||
110 | public bool ContainsKey(K key) |
||
111 | { |
||
39 | office | 112 | SyncRoot.EnterReadLock(); |
113 | var c = store.ContainsKey(key); |
||
114 | SyncRoot.ExitReadLock(); |
||
115 | return c; |
||
22 | office | 116 | } |
117 | |||
118 | public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) |
||
119 | { |
||
39 | office | 120 | SyncRoot.EnterReadLock(); |
27 | office | 121 | ((IDictionary<K, V>)store).CopyTo(array, arrayIndex); |
39 | office | 122 | SyncRoot.ExitReadLock(); |
22 | office | 123 | } |
124 | |||
125 | public IEnumerator<KeyValuePair<K, V>> GetEnumerator() |
||
126 | { |
||
39 | office | 127 | SyncRoot.EnterReadLock(); |
128 | var enumerator = ((IDictionary<K, V>)store).GetEnumerator(); |
||
129 | SyncRoot.ExitReadLock(); |
||
130 | return enumerator; |
||
22 | office | 131 | } |
132 | |||
133 | public bool Remove(KeyValuePair<K, V> item) |
||
134 | { |
||
39 | office | 135 | SyncRoot.EnterWriteLock(); |
27 | office | 136 | var removed = ((IDictionary<K, V>)store).Remove(item); |
39 | office | 137 | SyncRoot.ExitWriteLock(); |
22 | office | 138 | IsVirgin = false; |
139 | if (removed) |
||
140 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); |
||
141 | return removed; |
||
142 | } |
||
143 | |||
144 | public bool Remove(K key) |
||
145 | { |
||
146 | KeyValuePair<K, V> item; |
||
39 | office | 147 | SyncRoot.EnterWriteLock(); |
22 | office | 148 | if (store.ContainsKey(key)) |
149 | item = new KeyValuePair<K, V>(key, store[key]); |
||
150 | |||
151 | var removed = store.Remove(key); |
||
39 | office | 152 | SyncRoot.ExitWriteLock(); |
22 | office | 153 | IsVirgin = false; |
154 | if (removed) |
||
155 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); |
||
156 | return removed; |
||
157 | } |
||
158 | |||
159 | public bool TryGetValue(K key, out V value) |
||
160 | { |
||
39 | office | 161 | SyncRoot.EnterReadLock(); |
162 | var c = store.TryGetValue(key, out value); |
||
163 | SyncRoot.ExitReadLock(); |
||
164 | return c; |
||
22 | office | 165 | } |
166 | |||
167 | IEnumerator IEnumerable.GetEnumerator() |
||
168 | { |
||
39 | office | 169 | SyncRoot.EnterReadLock(); |
170 | var enumerator = ((IDictionary<K, V>)store).GetEnumerator(); |
||
171 | SyncRoot.ExitReadLock(); |
||
172 | return enumerator; |
||
22 | office | 173 | } |
174 | |||
175 | public event NotifyCollectionChangedEventHandler CollectionChanged; |
||
176 | |||
177 | private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) |
||
178 | { |
||
179 | CollectionChanged?.Invoke(this, args); |
||
180 | } |
||
181 | } |
||
27 | office | 182 | } |