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