在开发中,对于内置值类型和string我们可以通过封装属性在Set中监听写入操作,但是对于Dictionary、List等就不能监听到Add、Remove等写入操作。
所以一般采取两种方式监听它们的读写操作,一种是封装操作方法,间接进行监听,第二种就是重写Add和Remove等方法。下面介绍第二种方法。
下面是重写了Dictionary的示例,List同理。
using System;
using System.Collections.Generic;
// 定义一个委托类型,用于处理字典变化的事件
public delegate void DictionaryChangedEventHandler<TKey, TValue>(object sender, DictionaryChangedEventArgs<TKey, TValue> e);
// 定义一个事件参数类,用于封装字典变化的信息
public class DictionaryChangedEventArgs<TKey, TValue> : EventArgs
{
// 变化的类型,可以是Add, Remove, Update或Clear
public DictionaryChangedType ChangeType { get; set; }
// 变化的键
public TKey Key { get; set; }
// 变化的值
public TValue Value { get; set; }
// 构造函数
public DictionaryChangedEventArgs(DictionaryChangedType changeType, TKey key, TValue value)
{
ChangeType = changeType;
Key = key;
Value = value;
}
}
// 定义一个枚举类型,用于表示字典变化的类型
public enum DictionaryChangedType
{
Init,
Add,
Remove,
Update,
Clear,
}
// 定义一个继承自Dictionary<TKey,TValue>的类,用于触发字典变化的事件
public class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
// 定义一个构造函数,用于接受一个IDictionary<TKey, TValue>类型的参数
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
{
base.Clear();
foreach (var item in dictionary)
{
base.Add(item.Key, item.Value);
}
OnDictionaryChanged(new DictionaryChangedEventArgs<TKey, TValue>(DictionaryChangedType.Init, default, default));
}
public ObservableDictionary()
{
OnDictionaryChanged(new DictionaryChangedEventArgs<TKey, TValue>(DictionaryChangedType.Init, default, default));
}
// 定义一个事件,用于通知字典变化
public event DictionaryChangedEventHandler<TKey, TValue> DictionaryChanged;
// 重写Add方法,用于在添加元素时触发事件
public new void Add(TKey key, TValue value)
{
base.Add(key, value);
OnDictionaryChanged(new DictionaryChangedEventArgs<TKey, TValue>(DictionaryChangedType.Add, key, value));
}
// 重写Remove方法,用于在删除元素时触发事件
public new bool Remove(TKey key)
{
if (base.TryGetValue(key, out TValue value))
{
base.Remove(key);
OnDictionaryChanged(new DictionaryChangedEventArgs<TKey, TValue>(DictionaryChangedType.Remove, key, value));
return true;
}
return false;
}
// 重写索引器,用于在更新元素时触发事件
public new TValue this[TKey key]
{
get => base[key];
set
{
if (base.ContainsKey(key))
{
base[key] = value;
OnDictionaryChanged(new DictionaryChangedEventArgs<TKey, TValue>(DictionaryChangedType.Update, key, value));
}
else
{
Add(key, value);
}
}
}
// 重写Clear方法,用于在清空字典时触发事件
public new void Clear()
{
base.Clear();
OnDictionaryChanged(new DictionaryChangedEventArgs<TKey, TValue>(DictionaryChangedType.Clear, default, default));
}
// 定义一个虚方法,用于触发事件
protected virtual void OnDictionaryChanged(DictionaryChangedEventArgs<TKey, TValue> e)
{
DictionaryChanged?.Invoke(this, e);
}
public void ResetSubscriptions()
{
DictionaryChanged = null;
}
}
使用示例
public void Test()
{
// 创建一个ObservableDictionary实例
var dict = new ObservableDictionary<string, int>();
// 注册事件处理程序,用于输出字典变化的信息
dict.DictionaryChanged += (sender, e) =>
{
Debug.Log($"ChangeType: {e.ChangeType}, Key: {e.Key}, Value: {e.Value}");
};
// 添加元素
dict.Add("a", 1);
dict.Add("b", 2);
// 删除元素
dict.Remove("a");
// 更新元素
dict["b"] = 3;
dict["c"] = 4;
Dictionary<string, int> newDic = new Dictionary<string, int>
{
{ "acd", 120 }
};
Debug.LogError(((ObservableDictionary<string, int>)newDic).Count);
var newDic1 = new ObservableDictionary<string, int>(newDic);
Debug.LogError(newDic1.Count);
// 清空字典
dict.Clear();
}