using System; using System.Collections.Generic; namespace UniRx { public sealed class DictionaryDisposable : IDisposable, IDictionary where TValue : IDisposable { bool isDisposed = false; readonly Dictionary inner; public DictionaryDisposable() { inner = new Dictionary(); } public DictionaryDisposable(IEqualityComparer comparer) { inner = new Dictionary(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.KeyCollection Keys { get { throw new NotSupportedException("please use .Select(x => x.Key).ToArray()"); } } public Dictionary.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.Enumerator GetEnumerator() { lock (inner) { return new Dictionary(inner).GetEnumerator(); } } bool ICollection>.IsReadOnly { get { return ((ICollection>)inner).IsReadOnly; } } ICollection IDictionary.Keys { get { lock (inner) { return new List(inner.Keys); } } } ICollection IDictionary.Values { get { lock (inner) { return new List(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>.Add(KeyValuePair item) { Add((TKey)item.Key, (TValue)item.Value); } bool ICollection>.Contains(KeyValuePair item) { lock (inner) { return ((ICollection>)inner).Contains(item); } } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { lock (inner) { ((ICollection>)inner).CopyTo(array, arrayIndex); } } IEnumerator> IEnumerable>.GetEnumerator() { lock (inner) { return new List>((ICollection>)inner).GetEnumerator(); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } bool ICollection>.Remove(KeyValuePair item) { throw new NotSupportedException(); } public void Dispose() { lock (inner) { if (isDisposed) return; isDisposed = true; foreach (var item in inner) { item.Value.Dispose(); } inner.Clear(); } } } }