#if UNITY_5_3_OR_NEWER using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace RocketUtils { [Serializable] public class ObservableDict : IDictionary, ISerializationCallbackReceiver { public event Action Changed; [SerializeField] private Dictionary _dict; #region IDictionary Properties public ICollection Keys { get { return _dict.Keys; } } public ICollection Values { get { return _dict.Values; } } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return false; } } public TValue this[TKey key] { get { return _dict[key]; } set { _dict[key] = value; RaiseChangedEvent(); } } #endregion public ObservableDict() { _dict = new Dictionary(); } public ObservableDict(ObservableDict other) { _dict = new Dictionary(); var keys = other.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { var value = other[keys[i]]; _dict.Add(keys[i], value); IObservableModel observableItem = value as IObservableModel; if (observableItem != null) observableItem.PropertyChanged += RaiseChangedEvent; } } ~ObservableDict() { Clear(); } private void RaiseChangedEvent() { if (Changed != null) Changed.Invoke(); } #region IDictionary Methods public void Add(TKey key, TValue value) { try { _dict.Add(key, value); } catch (ArgumentException e) { throw e; } RaiseChangedEvent(); IObservableModel observableItem = value as IObservableModel; if (observableItem != null) observableItem.PropertyChanged += RaiseChangedEvent; } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public bool Remove(TKey key) { if (_dict.ContainsKey(key)) { var value = _dict[key]; IObservableModel observableItem = value as IObservableModel; if (observableItem != null) observableItem.PropertyChanged -= RaiseChangedEvent; _dict.Remove(key); RaiseChangedEvent(); return true; } return false; } public bool TryGetValue(TKey key, out TValue value) { return _dict.TryGetValue(key, out value); } public void Add(KeyValuePair item) { try { Add(item.Key, item.Value); } catch (ArgumentException e) { throw e; } } public void Clear() { if (_dict == null) { return; } foreach (var pair in _dict) { IObservableModel observableItem = pair.Value as IObservableModel; if (observableItem != null) observableItem.PropertyChanged -= RaiseChangedEvent; } _dict.Clear(); RaiseChangedEvent(); } public bool Contains(KeyValuePair item) { return _dict.ContainsKey(item.Key) && _dict[item.Key].Equals(item.Value); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { throw new NotImplementedException(); } public bool Remove(KeyValuePair item) { throw new NotImplementedException(); } public IEnumerator> GetEnumerator() { return _dict.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _dict.GetEnumerator(); } #endregion #region Serialization Callbacks [SerializeField] private TKey[] _keys; [SerializeField] private TValue[] _values; public void OnAfterDeserialize() { if (_keys != null && _values != null) { if (_dict == null) _dict = new Dictionary(_keys.Length); else _dict.Clear(); for (int i = 0; i < _keys.Length; i++) { if (i < _values.Length) _dict[_keys[i]] = _values[i]; else _dict[_keys[i]] = default(TValue); } } _keys = null; _values = null; } public void OnBeforeSerialize() { if (_dict == null || _dict.Count == 0) { _keys = null; _values = null; } else { int cnt = _dict.Count; _keys = new TKey[cnt]; _values = new TValue[cnt]; int i = 0; var e = _dict.GetEnumerator(); while (e.MoveNext()) { _keys[i] = e.Current.Key; _values[i] = e.Current.Value; i++; } e.Dispose(); } } #endregion } } #endif