自定义实现Dictionary类似效果 线程安全
程序员文章站
2022-03-09 10:44:36
...
/// <summary>
/// 字典类 获取出来都是副本,不可直接更改,需要手动调用UPDATE方法更新,支持线程安全
/// 使用:Add 添加 、Update 进行修改 会追踪是否修改,一旦修改自动更新原始值!
/// 日志输出
/// 方法:Keys,ContainsKey,Count,Add,Update,Remove,Clear,ToList
/// auth: Time 2020-4-2
/// </summary>
public class CustomsParameterDictionary<TKey, TKey1, TValue>
{
/// <summary>
/// 是否输出日志
/// </summary>
private bool _log = false;
/// <summary>
/// 字典类 获取出来都是副本,不可直接更改,需要手动调用UPDATE方法更新,支持线程安全
/// </summary>
/// <param name="log">是否开启日志记录</param>
public CustomsParameterDictionary(bool log = false)
{
_log = log;
}
//队列安全访问
static object _lock = new object();
/// <summary>
/// 内部储存
/// </summary>
Dictionary<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>> array = new Dictionary<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>();
/// <summary>
/// 锁定操作访问
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="func">执行方法</param>
/// <returns></returns>
T LockAction<T>(Func<T> func)
{
Exception exs = null;
lock (_lock)
{
try
{
return func();
}
catch (Exception ex)
{
exs = ex;
}
}
if (exs != null)
throw exs;
return default;
}
/// <summary>
/// 锁定操作访问
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="action">执行方法</param>
/// <returns></returns>
void LockAction(Action action)
{
//避免异常异常后解锁并且抛出异常
Exception exs = null;
lock (_lock)
{
try
{
action();
}
catch (Exception ex)
{
exs = ex;
}
}
if (exs != null)
throw exs;
}
/// <summary>
/// 索引器 使用副本
/// </summary>
/// <param name="tkey"></param>
/// <returns></returns>
public List<CustomsParameterKeyValue<TKey1, TValue>> this[TKey tkey]
{
get
{
return LockAction(() =>
{
var list = new List<CustomsParameterKeyValue<TKey1, TValue>>();
var arrayList = array[tkey];
for (int i = 0; i < arrayList.Count; i++)
list.Add(new CustomsParameterKeyValue<TKey1, TValue>(arrayList[i].Key, arrayList[i].Value));
return list;
});
}
}
/// <summary>
/// 索引器
/// </summary>
/// <param name="tkey">主KEY</param>
/// <param name="key1">子KEY</param>
/// <returns></returns>
public TValue this[TKey tkey, TKey1 key1]
{
get
{
return LockAction(() =>
{
return ChildKey(tkey, key1).Value;
});
}
}
/// <summary>
/// 通过子节点查询对应本身
/// </summary>
/// <param name="tkey">主Key</param>
/// <param name="tkey1">子Key</param>
/// <returns></returns>
CustomsParameterKeyValue<TKey1, TValue> ChildKey(TKey tkey, TKey1 tkey1)
{
if (!ContainsKey(tkey))
throw new AggregateException("不存在当前KEY值:" + tkey);
foreach (var item in array)
{
if (item.Key.Equals(tkey))
{
foreach (var itemvalue in item.Value)
{
if (itemvalue.Key.Equals(tkey1))
return itemvalue;
}
}
}
throw new AggregateException("不存在当前KEY1值:" + tkey);
}
/// <summary>
/// 获取所有Key
/// </summary>
public ICollection<TKey> Keys
{
get
{
return LockAction(() =>
{
return array.Keys;
});
}
}
/// <summary>
/// 总条数
/// </summary>
public int Count => LockAction(() => array.Count);
/// <summary>
/// 是否存在Key
/// </summary>
/// <param name="tkey"></param>
/// <returns></returns>
public bool ContainsKey(TKey tkey)
{
return LockAction(() =>
{
return array.ContainsKey(tkey);
});
}
/// <summary>
/// 是否存在Key
/// </summary>
/// <param name="tkey"></param>
/// <param name="key1"></param>
/// <returns></returns>
public bool ContainsKey(TKey tkey, TKey1 key1)
{
return LockAction(() =>
{
if (array.ContainsKey(tkey))
{
foreach (var item in array[tkey])
{
if (item.Key.Equals(key1))
return true;
}
}
return false;
});
}
/// <summary>
/// 添加元素
/// </summary>
/// <param name="key"></param>
/// <param name="key1"></param>
/// <param name="value"></param>
public void Add(TKey key, TKey1 key1, TValue value)
{
LockAction(() =>
{
if (ContainsKey(key))
{
if (ContainsKey(key, key1))
throw new ArgumentException("添加主KEY:" + key + " 子KEY:" + key1 + " 已存在!");
else
array[key].Add(new CustomsParameterKeyValue<TKey1, TValue>(key1, value));
}
else
{
array.Add(key, new List<CustomsParameterKeyValue<TKey1, TValue>>
{
new CustomsParameterKeyValue<TKey1, TValue>(key1, value)
});
}
});
}
/// <summary>
/// 跟踪变化进行修改
/// </summary>
/// <param name="value"></param>
public delegate void TrackingAction(ref CustomsParameterKeyValue<TKey1, TValue> value);
/// <summary>
/// 添加元素
/// </summary>
/// <param name="key">Key</param>
/// <param name="key1">子Key</param>
/// <param name="trackaction">CustomsParameterKeyValue<TKey1, TValue></param>
public void Update(TKey key, TKey1 key1, TrackingAction trackaction)
{
LockAction(() =>
{
if (!ContainsKey(key))
throw new ArgumentException("不存在当前KEY值" + key);
var model = ChildKey(key, key1);
var copy = new CustomsParameterKeyValue<TKey1, TValue>
{
Key = model.Key,
Value = model.Value
};
if (_log)
{
Trace.WriteLine("-----------------------------");
Trace.WriteLine("之前的值:" + model.Value);
}
trackaction(ref copy);
if (_log)
Trace.WriteLine("之后的值:" + copy.Value);
if (model.Key.Equals(copy.Key))
model.Value = copy.Value;
else
{
if (ContainsKey(key, key1))
throw new AggregateException("主KEY:" + key + " KEY1:" + key1 + " 修改KEY1:" + key + " 已存在!");
model.Key = copy.Key;
model.Value = copy.Value;
}
if (_log)
{
var sb = new StringBuilder();
sb.Append("店铺:" + key1 + System.Environment.NewLine);
sb.Append("线程:" + Thread.CurrentThread.ManagedThreadId.ToString());
Trace.WriteLine(sb.ToString());
Trace.WriteLine("-----------------------------");
}
});
}
/// <summary>
/// 移除指定KEY
/// </summary>
/// <param name="tkey">key</param>
/// <returns></returns>
public bool Remove(TKey tkey)
{
return LockAction(() =>
{
if (ContainsKey(tkey))
array.Remove(tkey);
return true;
});
}
/// <summary>
/// 移除指定KEY
/// </summary>
/// <param name="tkey">主key</param>
/// <param name="key1">子key</param>
/// <returns></returns>
public bool Remove(TKey tkey, TKey1 key1)
{
return LockAction(() =>
{
if (ContainsKey(tkey))
{
for (int i = 0; i < array[tkey].Count; i++)
{
var model = array[tkey][i];
if (model.Key.Equals(key1))
{
array[tkey].RemoveAt(i);
break;
}
}
}
return true;
});
}
/// <summary>
/// 清空
/// </summary>
public void Clear()
{
LockAction(() =>
{
array.Clear();
array = null;
array = new Dictionary<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>();
});
}
/// <summary>
/// 获取所有值
/// </summary>
/// <returns></returns>
public IEnumerator<KeyValuePair<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>> GetEnumerator()
{
var list = LockAction(() =>
{
var copy = new List<KeyValuePair<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>>();
foreach (var item in array)
{
var key1value = new List<CustomsParameterKeyValue<TKey1, TValue>>();
foreach (var keyvalueitem in item.Value)
key1value.Add(new CustomsParameterKeyValue<TKey1, TValue>(keyvalueitem.Key, keyvalueitem.Value));
copy.Add(
new KeyValuePair<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>(item.Key, key1value));
}
return copy;
});
foreach (var item in list)
{
yield return item;
}
}
/// <summary>
/// ToList
/// </summary>
/// <returns></returns>
public List<KeyValuePair<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>> ToList()
{
var array = new List<KeyValuePair<TKey, List<CustomsParameterKeyValue<TKey1, TValue>>>>();
var enumerator = GetEnumerator();
while (enumerator.MoveNext())
array.Add(enumerator.Current);
return array;
}
}
/// <summary>
/// 模型
/// </summary>
/// <typeparam name="TKeys">key</typeparam>
/// <typeparam name="TValues">value</typeparam>
public class CustomsParameterKeyValue<TKeys, TValues>
{
/// <summary>
/// init
/// </summary>
public CustomsParameterKeyValue()
{
}
/// <summary>
/// init
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public CustomsParameterKeyValue(TKeys key, TValues value)
{
Key = key;
Value = value;
}
public TKeys Key
{
get; set;
}
public TValues Value
{
get; set;
}
}