XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.AutoConfig

【DLL】自动实现配置文件的存储

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;

namespace XFEExtension.NetCore.AutoConfig;

/// <summary>
/// 支持线程安全访问和合并自动保存的配置文件字典
/// </summary>
/// <typeparam name="TKey">字典Key泛型</typeparam>
/// <typeparam name="TValue">字典Value泛型</typeparam>
public class ProfileDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable, IProfileOwnedCollection where TKey : notnull
{
    private readonly Dictionary<TKey, TValue> _innerDictionary;
    private readonly object _syncRoot = new();
    private XFEProfile? _currentProfile;

    /// <summary>
    /// 创建空字典
    /// </summary>
    public ProfileDictionary() => _innerDictionary = [];

    /// <summary>
    /// 使用现有字典创建
    /// </summary>
    /// <param name="innerDictionary">现有字典</param>
    public ProfileDictionary(Dictionary<TKey, TValue> innerDictionary) => _innerDictionary = innerDictionary;

    ///<inheritdoc/>
    public TValue this[TKey key]
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary[key];
        }
        set
        {
            lock (_syncRoot)
            {
                _innerDictionary[key] = value;
                RequestSave();
            }
        }
    }

    ///<inheritdoc/>
    public object? this[object key]
    {
        get
        {
            lock (_syncRoot)
                return ((IDictionary)_innerDictionary)[key];
        }
        set
        {
            lock (_syncRoot)
            {
                ((IDictionary)_innerDictionary)[key] = value;
                RequestSave();
            }
        }
    }

    ///<inheritdoc/>
    public int Count
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Count;
        }
    }

    /// <summary>
    /// 当前配置文件实例
    /// </summary>
    public XFEProfile? CurrentProfile
    {
        get
        {
            lock (_syncRoot)
                return _currentProfile;
        }
        set
        {
            lock (_syncRoot)
                _currentProfile = value;
        }
    }

    ///<inheritdoc/>
    public bool IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).IsReadOnly;

    ///<inheritdoc/>
    public ICollection<TKey> Keys
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Keys.ToArray();
        }
    }

    ///<inheritdoc/>
    public ICollection<TValue> Values
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Values.ToArray();
        }
    }

    ///<inheritdoc/>
    public bool IsSynchronized => true;

    ///<inheritdoc/>
    public object SyncRoot => _syncRoot;

    ///<inheritdoc/>
    public bool IsFixedSize => ((IDictionary)_innerDictionary).IsFixedSize;

    IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Keys.ToArray();
        }
    }

    ICollection IDictionary.Keys
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Keys.ToArray();
        }
    }

    IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Values.ToArray();
        }
    }

    ICollection IDictionary.Values
    {
        get
        {
            lock (_syncRoot)
                return _innerDictionary.Values.ToArray();
        }
    }

    ///<inheritdoc/>
    public void Add(KeyValuePair<TKey, TValue> item)
    {
        lock (_syncRoot)
        {
            ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Add(item);
            RequestSave();
        }
    }

    ///<inheritdoc/>
    public void Add(TKey key, TValue value)
    {
        lock (_syncRoot)
        {
            _innerDictionary.Add(key, value);
            RequestSave();
        }
    }

    ///<inheritdoc/>
    public void Add(object key, object? value)
    {
        lock (_syncRoot)
        {
            ((IDictionary)_innerDictionary).Add(key, value);
            RequestSave();
        }
    }

    ///<inheritdoc/>
    public void Clear()
    {
        lock (_syncRoot)
        {
            if (_innerDictionary.Count == 0)
                return;
            _innerDictionary.Clear();
            RequestSave();
        }
    }

    ///<inheritdoc/>
    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        lock (_syncRoot)
            return ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Contains(item);
    }

    ///<inheritdoc/>
    public bool Contains(object key)
    {
        lock (_syncRoot)
            return ((IDictionary)_innerDictionary).Contains(key);
    }

    ///<inheritdoc/>
    public bool ContainsKey(TKey key)
    {
        lock (_syncRoot)
            return _innerDictionary.ContainsKey(key);
    }

    ///<inheritdoc/>
    public bool ContainsValue(TValue value)
    {
        lock (_syncRoot)
            return _innerDictionary.ContainsValue(value);
    }

    ///<inheritdoc/>
    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        lock (_syncRoot)
            ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).CopyTo(array, arrayIndex);
    }

    ///<inheritdoc/>
    public void CopyTo(Array array, int index)
    {
        lock (_syncRoot)
            ((ICollection)_innerDictionary).CopyTo(array, index);
    }

    ///<inheritdoc/>
    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        lock (_syncRoot)
            return new Dictionary<TKey, TValue>(_innerDictionary, _innerDictionary.Comparer).GetEnumerator();
    }

    ///<inheritdoc/>
    [Obsolete]
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        lock (_syncRoot)
            ((ISerializable)_innerDictionary).GetObjectData(info, context);
    }

    ///<inheritdoc/>
    public void OnDeserialization(object? sender)
    {
        lock (_syncRoot)
            ((IDeserializationCallback)_innerDictionary).OnDeserialization(sender);
    }

    ///<inheritdoc/>
    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        lock (_syncRoot)
        {
            var result = ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Remove(item);
            if (result)
                RequestSave();
            return result;
        }
    }

    ///<inheritdoc/>
    public bool Remove(TKey key)
    {
        lock (_syncRoot)
        {
            var result = _innerDictionary.Remove(key);
            if (result)
                RequestSave();
            return result;
        }
    }

    ///<inheritdoc/>
    public void Remove(object key)
    {
        lock (_syncRoot)
        {
            var count = _innerDictionary.Count;
            ((IDictionary)_innerDictionary).Remove(key);
            if (_innerDictionary.Count != count)
                RequestSave();
        }
    }

    ///<inheritdoc/>
    public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
    {
        lock (_syncRoot)
            return _innerDictionary.TryGetValue(key, out value);
    }

    ///<inheritdoc/>
    public bool TryAdd(TKey key, TValue value)
    {
        lock (_syncRoot)
        {
            var result = _innerDictionary.TryAdd(key, value);
            if (result)
                RequestSave();
            return result;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        lock (_syncRoot)
            return ((IEnumerable)new Dictionary<TKey, TValue>(_innerDictionary, _innerDictionary.Comparer)).GetEnumerator();
    }

    IDictionaryEnumerator IDictionary.GetEnumerator()
    {
        lock (_syncRoot)
            return ((IDictionary)new Dictionary<TKey, TValue>(_innerDictionary, _innerDictionary.Comparer)).GetEnumerator();
    }

    private void RequestSave() => _currentProfile?.InstanceRequestSaveProfile();
}