123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- namespace IFramework
- {
- /// <summary>
- /// 可观测Dictionary
- /// </summary>
- /// <typeparam name="TKey">TKey</typeparam>
- /// <typeparam name="TValue">TValue</typeparam>
- public class ObservableDictionary<TKey, TValue> : Unit, IDictionary<TKey, TValue>, IDictionary
- {
- #region 事件与变量定义
- private Action<KeyValuePair<TKey, TValue>> onKeyValuePairAdded;
- private Action<KeyValuePair<TKey, TValue>, KeyValuePair<TKey, TValue>> onKeyValuePairReplaced;
- private Action<KeyValuePair<TKey, TValue>> onKeyValuePairRemoved;
- private Action onClear;
- private Action<KeyValuePair<TKey, TValue>[]> onKeyValuePairRangeAdded;
- private Lazy<Dictionary<TKey, TValue>> _dictionary = new Lazy<Dictionary<TKey, TValue>>(() => { return new Dictionary<TKey, TValue>(); });
- private Dictionary<TKey, TValue> dictionary { get { return _dictionary.Value; } }
- #endregion
- #region 注册与移除监听方法
- /// <summary>
- /// 注册方法 添加键值对
- /// </summary>
- /// <param name="action">
- /// action arg1 : the Added KeyValuePair of <typeparamref name="TKey" /> and <typeparamref name="TValue" /><br/>
- /// 参数1为添加的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" />
- /// </param>
- public void SubscribeAddKeyValuePair(Action<KeyValuePair<TKey, TValue>> action)
- {
- onKeyValuePairAdded += action;
- }
- /// <summary>
- /// 移除方法 添加键值对
- /// </summary>
- /// <param name="action">
- /// action arg1 : the Added KeyValuePair of <typeparamref name="TKey" /> and <typeparamref name="TValue" /><br/>
- /// 参数1为添加的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" />
- /// </param>
- public void UnSubscribeAddKeyValuePair(Action<KeyValuePair<TKey, TValue>> action)
- {
- onKeyValuePairAdded -= action;
- }
- /// <summary>
- /// 注册方法 替换键值对
- /// </summary>
- /// <param name = "action" >
- /// action arg1 : the old KeyValuePair of <typeparamref name="TKey" /> and <typeparamref name="TValue" /> which has been replaced<br/>
- /// 参数1为被替换的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" /><br/><br/>
- /// action arg2 : the new KeyValuePair of <typeparamref name="TKey" /> and <typeparamref name="TValue" /> which replaced the old one<br/>
- /// 参数1为新的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" /><br/>
- /// </param>
- public void SubscribeReplaceKeyValuePair(Action<KeyValuePair<TKey, TValue>, KeyValuePair<TKey, TValue>> action)
- {
- onKeyValuePairReplaced += action;
- }
- /// <summary>
- /// 移除方法 替换键值对
- /// </summary>
- /// <param name = "action" >
- /// action arg1 : the old KeyValuePair of <typeparamref name="TKey" /> and <typeparamref name="TValue" /> which has been replaced<br/>
- /// 参数1为被替换的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" /><br/><br/>
- /// action arg2 : the new KeyValuePair of <typeparamref name="TKey" /> and <typeparamref name="TValue" /> which replaced the old one<br/>
- /// 参数1为新的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" /><br/>
- /// </param>
- public void UnSubscribeReplaceKeyValuePair(Action<KeyValuePair<TKey, TValue>, KeyValuePair<TKey, TValue>> action)
- {
- onKeyValuePairReplaced -= action;
- }
- /// <summary>
- /// 注册方法 移除键值对
- /// </summary>
- /// <param name="action">
- /// action arg1 : the removed KeyValuePair with <typeparamref name="TKey" /> and <typeparamref name="TValue" /><br/>
- /// 参数1为移除的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" />
- /// </param>
- public void SubscribeRemoveKeyValuePair(Action<KeyValuePair<TKey, TValue>> action)
- {
- onKeyValuePairRemoved += action;
- }
- /// <summary>
- /// 移除方法 移除键值对
- /// </summary>
- /// <param name="action">
- /// action arg1 : the removed KeyValuePair with <typeparamref name="TKey" /> and <typeparamref name="TValue" /><br/>
- /// 参数1为移除的键值对对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" />
- /// </param>
- public void UnSubscribeRemoveKeyValuePair(Action<KeyValuePair<TKey, TValue>> action)
- {
- onKeyValuePairRemoved -= action;
- }
- /// <summary>
- /// 注册方法 清除所有键值对
- /// </summary>
- /// <param name="action">none arg Action</param>
- public void SubscribeClear(Action action)
- {
- onClear += action;
- }
- /// <summary>
- /// 移除方法 清除所有键值对
- /// </summary>
- /// <param name="action">none arg Action</param>
- public void UnSbscribeClear(Action action)
- {
- onClear -= action;
- }
- /// <summary>
- /// 注册方法 添加多个键值对
- /// </summary>
- /// <param name="action">
- /// action arg1 : the Added array of KeyValuePair with <typeparamref name="TKey" /> and <typeparamref name="TValue" /><br/>
- /// 参数1为添加的键值对数组对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" />
- /// </param>
- public void SubscribeAddRange(Action<KeyValuePair<TKey, TValue>[]> action)
- {
- onKeyValuePairRangeAdded += action;
- }
- /// <summary>
- /// 移除方法 添加添加多个键值对
- /// </summary>
- /// <param name="action">
- /// action arg1 : the Added array of KeyValuePair with <typeparamref name="TKey" /> and <typeparamref name="TValue" /><br/>
- /// 参数1为添加的键值对数组对象,键的类型为<typeparamref name="TKey" />,值的类型为<typeparamref name="TValue" />
- /// </param>
- public void UnSubscribeAddRange(Action<KeyValuePair<TKey, TValue>[]> action)
- {
- onKeyValuePairRangeAdded -= action;
- }
- #endregion
- #region 接口实现
- /// <summary>
- /// 索引器
- /// </summary>
- /// <param name="key">键</param>
- /// <returns>值</returns>
- public TValue this[TKey key]
- {
- get
- {
- if (!dictionary.ContainsKey(key))
- return default(TValue);
- return dictionary[key];
- }
- set
- {
- Insert(key, value, false);
- }
- }
- /// <summary>
- /// 键集合
- /// </summary>
- public ICollection<TKey> Keys
- {
- get { return dictionary.Keys; }
- }
- /// <summary>
- /// 值集合
- /// </summary>
- public ICollection<TValue> Values
- {
- get { return dictionary.Values; }
- }
- /// <summary>
- /// 数量
- /// </summary>
- public int Count
- {
- get { return dictionary.Count; }
- }
- /// <summary>
- /// 是否只读
- /// </summary>
- public bool IsReadOnly
- {
- get { return ((IDictionary)this.dictionary).IsReadOnly; }
- }
- /// <summary>
- /// 添加键值对
- /// </summary>
- /// <param name="key">键</param>
- /// <param name="value">值</param>
- public void Add(TKey key, TValue value)
- {
- Insert(key, value, true);
- }
- /// <summary>
- /// 添加键值对
- /// </summary>
- /// <param name="pair">键值对</param>
- public void Add(KeyValuePair<TKey, TValue> pair)
- {
- Insert(pair.Key, pair.Value, true);
- }
- /// <summary>
- /// 清除所有键值对
- /// </summary>
- public void Clear()
- {
- if (dictionary.Count > 0)
- {
- dictionary.Clear();
- onClear?.Invoke();
- }
- }
- /// <summary>
- /// 是否存在键值对
- /// </summary>
- /// <param name="pair">键值对</param>
- /// <returns></returns>
- public bool Contains(KeyValuePair<TKey, TValue> pair)
- {
- return dictionary.Contains(pair);
- }
- /// <summary>
- /// 是否存在键
- /// </summary>
- /// <param name="key">键</param>
- /// <returns>存在情况</returns>
- public bool ContainsKey(TKey key)
- {
- return dictionary.ContainsKey(key);
- }
- /// <summary>
- /// 将字典里的键值对拷贝到指定数组中
- /// </summary>
- /// <param name="array">接收的数组</param>
- /// <param name="arrayIndex">开始保存在数组的索引</param>
- public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
- {
- ((IDictionary)this.dictionary).CopyTo(array, arrayIndex);
- }
- /// <summary>
- /// 获取迭代器
- /// </summary>
- /// <returns>迭代器</returns>
- public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
- {
- return dictionary.GetEnumerator();
- }
- /// <summary>
- /// 删除键值对
- /// </summary>
- /// <param name="key">键</param>
- /// <returns>是否删除成功</returns>
- public bool Remove(TKey key)
- {
- if (key == null)
- throw new ArgumentNullException("key is null");
- dictionary.TryGetValue(key, out TValue value);
- var removed = dictionary.Remove(key);
- if (removed)
- {
- onKeyValuePairRemoved.Invoke(new KeyValuePair<TKey, TValue>(key, value));
- }
- return removed;
- }
- /// <summary>
- /// 删除键值对
- /// </summary>
- /// <param name="pair">键值对</param>
- /// <returns>是否删除成功,如果对应的键值对不存在,返回false</returns>
- public bool Remove(KeyValuePair<TKey, TValue> pair)
- {
- if (Contains(pair))
- {
- return Remove(pair.Key);
- }
- return false;
- }
- /// <summary>
- /// 获取指定键对应的值
- /// </summary>
- /// <param name="key">键</param>
- /// <param name="value">保存值的对象</param>
- /// <returns>是否获取成功</returns>
- public bool TryGetValue(TKey key, out TValue value)
- {
- return dictionary.TryGetValue(key, out value);
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)dictionary).GetEnumerator();
- }
- object IDictionary.this[object key]
- {
- get
- {
- return ((IDictionary)this.dictionary)[key];
- }
- set
- {
- Insert((TKey)key, (TValue)value, false);
- }
- }
- ICollection IDictionary.Keys
- {
- get { return ((IDictionary)this.dictionary).Keys; }
- }
- ICollection IDictionary.Values
- {
- get { return ((IDictionary)this.dictionary).Values; }
- }
- IDictionaryEnumerator IDictionary.GetEnumerator()
- {
- return ((IDictionary)this.dictionary).GetEnumerator();
- }
- bool IDictionary.Contains(object key)
- {
- return ((IDictionary)this.dictionary).Contains(key);
- }
- void IDictionary.Add(object key, object value)
- {
- this.Add((TKey)key, (TValue)value);
- }
- void IDictionary.Remove(object key)
- {
- this.Remove((TKey)key);
- }
- bool IDictionary.IsFixedSize
- {
- get { return ((IDictionary)this.dictionary).IsFixedSize; }
- }
- object ICollection.SyncRoot
- {
- get { return ((IDictionary)this.dictionary).SyncRoot; }
- }
- bool ICollection.IsSynchronized
- {
- get { return ((IDictionary)this.dictionary).IsSynchronized; }
- }
- void ICollection.CopyTo(Array array, int index)
- {
- ((IDictionary)this.dictionary).CopyTo(array, index);
- }
- /// <summary>
- /// 对象释放时调用(继承自Unit)
- /// </summary>
- protected override void OnDispose()
- {
- dictionary.Clear();
- onKeyValuePairAdded -= onKeyValuePairAdded;
- onKeyValuePairReplaced -= onKeyValuePairReplaced;
- onKeyValuePairRemoved -= onKeyValuePairRemoved;
- }
- #endregion
- #region 额外方法实现
- private void Insert(TKey key, TValue value, bool isAdd)
- {
- if (key == null)
- throw new ArgumentNullException("key is null");
- if (dictionary.TryGetValue(key, out TValue oldValue))
- {
- if (isAdd)
- throw new ArgumentException("this key has already been added");
- if (Equals(oldValue, value))
- return;
- dictionary[key] = value;
- onKeyValuePairReplaced?.Invoke(new KeyValuePair<TKey, TValue>(key, oldValue), new KeyValuePair<TKey, TValue>(key, value));
- }
- else
- {
- dictionary[key] = value;
- onKeyValuePairAdded?.Invoke(new KeyValuePair<TKey, TValue>(key, value));
- }
- }
- /// <summary>
- /// 将一个字典添加到另一个字典中
- /// </summary>
- /// <param name="items">字典对象</param>
- public void AddRange(IDictionary<TKey, TValue> items)
- {
- if (items == null)
- throw new ArgumentNullException("items is null");
- if (items.Count > 0)
- {
- if (items.Keys.Any((k) => this.dictionary.ContainsKey(k)))
- throw new ArgumentException("a key or some keys in this dictionary has already been added");
- else
- {
- foreach (var item in items)
- ((IDictionary<TKey, TValue>)this.dictionary).Add(item);
- }
- onKeyValuePairRangeAdded?.Invoke(items.ToArray());
- }
- }
- #endregion
- }
- }
|