You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
6.4 KiB
256 lines
6.4 KiB
1 year ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace UniRx
|
||
|
{
|
||
|
public sealed class DictionaryDisposable<TKey, TValue> : IDisposable, IDictionary<TKey, TValue>
|
||
|
where TValue : IDisposable
|
||
|
{
|
||
|
bool isDisposed = false;
|
||
|
readonly Dictionary<TKey, TValue> inner;
|
||
|
|
||
|
public DictionaryDisposable()
|
||
|
{
|
||
|
inner = new Dictionary<TKey, TValue>();
|
||
|
}
|
||
|
|
||
|
public DictionaryDisposable(IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
inner = new Dictionary<TKey, TValue>(comparer);
|
||
|
}
|
||
|
|
||
|
public TValue this[TKey key]
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return inner[key];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
if (isDisposed) value.Dispose();
|
||
|
|
||
|
TValue oldValue;
|
||
|
if (TryGetValue(key, out oldValue))
|
||
|
{
|
||
|
oldValue.Dispose();
|
||
|
inner[key] = value;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
inner[key] = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int Count
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return inner.Count;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Dictionary<TKey, TValue>.KeyCollection Keys
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
throw new NotSupportedException("please use .Select(x => x.Key).ToArray()");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Dictionary<TKey, TValue>.ValueCollection Values
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
throw new NotSupportedException("please use .Select(x => x.Value).ToArray()");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Add(TKey key, TValue value)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
if (isDisposed)
|
||
|
{
|
||
|
value.Dispose();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
inner.Add(key, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Clear()
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
foreach (var item in inner)
|
||
|
{
|
||
|
item.Value.Dispose();
|
||
|
}
|
||
|
inner.Clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool Remove(TKey key)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
TValue oldValue;
|
||
|
if (inner.TryGetValue(key, out oldValue))
|
||
|
{
|
||
|
var isSuccessRemove = inner.Remove(key);
|
||
|
if (isSuccessRemove)
|
||
|
{
|
||
|
oldValue.Dispose();
|
||
|
}
|
||
|
return isSuccessRemove;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool ContainsKey(TKey key)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return inner.ContainsKey(key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool TryGetValue(TKey key, out TValue value)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return inner.TryGetValue(key, out value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Dictionary<TKey, TValue>.Enumerator GetEnumerator()
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(inner).GetEnumerator();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ((ICollection<KeyValuePair<TKey, TValue>>)inner).IsReadOnly;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ICollection<TKey> IDictionary<TKey, TValue>.Keys
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return new List<TKey>(inner.Keys);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ICollection<TValue> IDictionary<TKey, TValue>.Values
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return new List<TValue>(inner.Values);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#if !UNITY_METRO
|
||
|
|
||
|
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
((System.Runtime.Serialization.ISerializable)inner).GetObjectData(info, context);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void OnDeserialization(object sender)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
((System.Runtime.Serialization.IDeserializationCallback)inner).OnDeserialization(sender);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||
|
{
|
||
|
Add((TKey)item.Key, (TValue)item.Value);
|
||
|
}
|
||
|
|
||
|
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return ((ICollection<KeyValuePair<TKey, TValue>>)inner).Contains(item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
((ICollection<KeyValuePair<TKey, TValue>>)inner).CopyTo(array, arrayIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
return new List<KeyValuePair<TKey, TValue>>((ICollection<KeyValuePair<TKey, TValue>>)inner).GetEnumerator();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||
|
{
|
||
|
return GetEnumerator();
|
||
|
}
|
||
|
|
||
|
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||
|
{
|
||
|
throw new NotSupportedException();
|
||
|
}
|
||
|
|
||
|
public void Dispose()
|
||
|
{
|
||
|
lock (inner)
|
||
|
{
|
||
|
if (isDisposed) return;
|
||
|
isDisposed = true;
|
||
|
|
||
|
foreach (var item in inner)
|
||
|
{
|
||
|
item.Value.Dispose();
|
||
|
}
|
||
|
inner.Clear();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|