欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义实现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;
        }
    }
相关标签: .NET ASP.NET