Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.Linq;
- namespace WpfApplication1 {
- /// <summary>
- /// ObservableDictionary implemented using ObservableCollection
- /// </summary>
- /// <remarks>O(n)</remarks>
- public class ObservableDictionary<TKey, TValue> : ObservableCollection<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue> {
- #region Private Fields
- private readonly IEqualityComparer<TKey> _comparer;
- #endregion
- #region Constructors
- public ObservableDictionary(IEqualityComparer<TKey> comparer = null) {
- this._comparer = comparer ?? EqualityComparer<TKey>.Default;
- }
- public ObservableDictionary(IEnumerable<KeyValuePair<TKey, TValue>> dictionary,
- IEqualityComparer<TKey> comparer = null)
- : base(dictionary) {
- this._comparer = comparer ?? EqualityComparer<TKey>.Default;
- }
- #endregion
- #region Public Methods
- private int FindIndexOfKey(TKey key) {
- for (int i = 0, count = base.Count; i < count; ++i) {
- if (_comparer.Equals(key, base[i].Key)) {
- return i;
- }
- }
- return -1;
- }
- public void Add(TKey key, TValue value) {
- if (FindIndexOfKey(key) != -1) {
- throw new ArgumentException("Key exists: " + key.ToString());
- }
- base.Add(new KeyValuePair<TKey, TValue>(key, value));
- }
- public bool Remove(TKey key) {
- var index = FindIndexOfKey(key);
- if (index == -1) {
- return false;
- }
- base.RemoveAt(index);
- return true;
- }
- public bool ContainsKey(TKey key) {
- return FindIndexOfKey(key) != -1;
- }
- public bool TryGetValue(TKey key, out TValue value) {
- var index = FindIndexOfKey(key);
- if (index == -1) {
- value = default(TValue);
- return false;
- }
- value = base[index].Value;
- return true;
- }
- #endregion
- #region Public Properties
- public TValue this[TKey key] {
- get {
- var index = FindIndexOfKey(key);
- if (index == -1) {
- throw new KeyNotFoundException(key.ToString());
- }
- return base[index].Value;
- }
- set {
- var index = FindIndexOfKey(key);
- if (index != -1) {
- base[index] = new KeyValuePair<TKey, TValue>(key, value);
- } else {
- base.Add(new KeyValuePair<TKey, TValue>(key, value));
- }
- }
- }
- IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys {
- get { return new KeyCollection(this); }
- }
- IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values {
- get { return new ValueCollection(this); }
- }
- public ICollection<TKey> Keys {
- get { return new KeyCollection(this); }
- }
- public ICollection<TValue> Values {
- get { return new ValueCollection(this); }
- }
- #endregion
- #region Internal Types
- public sealed class KeyCollection : IEnumerable<TKey>, ICollection<TKey> {
- private readonly ObservableDictionary<TKey, TValue> _dictionary;
- public KeyCollection(ObservableDictionary<TKey, TValue> dictionary) {
- _dictionary = dictionary;
- }
- public struct Enumerator : IEnumerator<TKey> {
- private ObservableDictionary<TKey, TValue> _dictionary;
- private int _index;
- internal Enumerator(ObservableDictionary<TKey, TValue> dictionary) {
- this._index = -1;
- this._dictionary = dictionary;
- }
- public TKey Current {
- get {
- Debug.Assert(_dictionary != null);
- Debug.Assert(_index >= 0 && _index < _dictionary.Count);
- return _dictionary[_index].Key;
- }
- }
- void IDisposable.Dispose() {
- _dictionary = null;
- }
- object System.Collections.IEnumerator.Current {
- get { return this.Current; }
- }
- public bool MoveNext() {
- Debug.Assert(_dictionary != null);
- Debug.Assert(_index >= -1 && _index < _dictionary.Count);
- return ++_index != _dictionary.Count;
- }
- public void Reset() {
- _index = 0;
- }
- }
- public IEnumerator<TKey> GetEnumerator() {
- return new Enumerator(_dictionary);
- }
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- return this.GetEnumerator();
- }
- void ICollection<TKey>.Add(TKey item) {
- throw new NotSupportedException();
- }
- void ICollection<TKey>.Clear() {
- throw new NotSupportedException();
- }
- void ICollection<TKey>.CopyTo(TKey[] array, int arrayIndex) {
- for (int index = 0, num = _dictionary.Count; index < num; ++index) {
- array[arrayIndex++] = _dictionary[index].Key;
- }
- }
- bool ICollection<TKey>.IsReadOnly {
- get { return true; }
- }
- public bool Contains(TKey item) {
- return _dictionary.ContainsKey(item);
- }
- public int Count {
- get { return _dictionary.Count; }
- }
- bool ICollection<TKey>.Remove(TKey item) {
- throw new NotSupportedException();
- }
- }
- public sealed class ValueCollection : IEnumerable<TValue>, ICollection<TValue> {
- private readonly ObservableDictionary<TKey, TValue> _dictionary;
- public ValueCollection(ObservableDictionary<TKey, TValue> dictionary) {
- _dictionary = dictionary;
- }
- public struct Enumerator : IEnumerator<TValue> {
- private ObservableDictionary<TKey, TValue> _dictionary;
- private int _index;
- internal Enumerator(ObservableDictionary<TKey, TValue> dictionary) {
- this._index = -1;
- this._dictionary = dictionary;
- }
- public TValue Current {
- get {
- Debug.Assert(_dictionary != null);
- Debug.Assert(_index >= 0 && _index < _dictionary.Count);
- return _dictionary[_index].Value;
- }
- }
- void IDisposable.Dispose() {
- _dictionary = null;
- }
- object System.Collections.IEnumerator.Current {
- get { return this.Current; }
- }
- public bool MoveNext() {
- Debug.Assert(_dictionary != null);
- Debug.Assert(_index >= -1 && _index < _dictionary.Count);
- return ++_index != _dictionary.Count;
- }
- public void Reset() {
- _index = 0;
- }
- }
- public IEnumerator<TValue> GetEnumerator() {
- return new Enumerator(_dictionary);
- }
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- return this.GetEnumerator();
- }
- void ICollection<TValue>.Add(TValue item) {
- throw new NotSupportedException();
- }
- void ICollection<TValue>.Clear() {
- throw new NotSupportedException();
- }
- void ICollection<TValue>.CopyTo(TValue[] array, int arrayIndex) {
- for (int index = 0, num = _dictionary.Count; index < num; ++index) {
- array[arrayIndex++] = _dictionary[index].Value;
- }
- }
- bool ICollection<TValue>.IsReadOnly {
- get { return true; }
- }
- public bool Contains(TValue item) {
- return _dictionary.Any(pair => pair.Value.Equals(item));
- }
- public int Count {
- get { return _dictionary.Count; }
- }
- bool ICollection<TValue>.Remove(TValue item) {
- throw new NotSupportedException();
- }
- }
- #endregion
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Linq;
- using NUnit.Framework;
- using WpfApplication1;
- using WpfApplication1.Model;
- namespace ClassLibrary1
- {
- [TestFixture]
- public class ObservableDictionaryTester {
- private ObservableDictionary<Profile, bool> _typingIndicators;
- private NotifyCollectionChangedEventArgs _lastEvent;
- [SetUp]
- public void Init() {
- _typingIndicators = new ObservableDictionary<Profile, bool> {
- new KeyValuePair<Profile, bool>(new Profile { Id = 1, FullName = "123" }, true),
- new KeyValuePair<Profile, bool>(new Profile { Id = 2, FullName = "234" }, false),
- };
- _lastEvent = null;
- _typingIndicators.CollectionChanged += OnCollectionChanged;
- }
- [TearDown]
- public void Cleanup() {
- _typingIndicators.CollectionChanged -= OnCollectionChanged;
- }
- private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
- _lastEvent = e;
- }
- [Test]
- public void TestAdd() {
- _typingIndicators.Add(new Profile { Id = 3, FullName = "345" }, false);
- Assert.AreEqual(3, _typingIndicators.Count);
- Assert.AreEqual("345", _typingIndicators[2].Key.FullName);
- Assert.AreEqual(NotifyCollectionChangedAction.Add, _lastEvent.Action);
- Assert.AreEqual(_typingIndicators[2], _lastEvent.NewItems[0]);
- _lastEvent = null;
- Assert.Throws<ArgumentException>(delegate {
- _typingIndicators.Add(new Profile { Id = 3, FullName = "345" }, true);
- });
- Assert.AreEqual(3, _typingIndicators.Count);
- Assert.Null(_lastEvent);
- }
- [Test]
- public void TestRemove() {
- Assert.True(_typingIndicators.Remove(new Profile { Id = 2 }));
- Assert.AreEqual(1, _typingIndicators.Count);
- Assert.AreEqual(NotifyCollectionChangedAction.Remove, _lastEvent.Action);
- Assert.AreEqual(2, ((KeyValuePair<Profile, bool>) _lastEvent.OldItems[0]).Key.Id);
- _lastEvent = null;
- Assert.False(_typingIndicators.Remove(new Profile { Id = 2 }));
- Assert.AreEqual(1, _typingIndicators.Count);
- Assert.Null(_lastEvent);
- }
- [Test]
- public void TestUpdate() {
- _typingIndicators[new Profile { Id = 2 }] = true;
- Assert.AreEqual(2, _typingIndicators.Count);
- Assert.True(_typingIndicators[1].Value);
- Assert.AreEqual(NotifyCollectionChangedAction.Replace, _lastEvent.Action);
- Assert.False(((KeyValuePair<Profile, bool>)_lastEvent.OldItems[0]).Value);
- Assert.True(((KeyValuePair<Profile, bool>)_lastEvent.NewItems[0]).Value);
- _lastEvent = null;
- _typingIndicators[new Profile { Id = 3 }] = false;
- Assert.AreEqual(3, _typingIndicators.Count);
- Assert.False(_typingIndicators[2].Value);
- Assert.NotNull(_lastEvent);
- Assert.AreEqual(NotifyCollectionChangedAction.Add, _lastEvent.Action);
- Assert.AreEqual(3, ((KeyValuePair<Profile, bool>)_lastEvent.NewItems[0]).Key.Id);
- Assert.False(((KeyValuePair<Profile, bool>)_lastEvent.NewItems[0]).Value);
- }
- [Test]
- public void TestGet() {
- Assert.False(_typingIndicators[new Profile { Id = 2 }]);
- bool value;
- Assert.Throws<KeyNotFoundException>(delegate {
- value = _typingIndicators[new Profile { Id = 3 }];
- });
- Assert.True(_typingIndicators.TryGetValue(new Profile { Id = 1 }, out value));
- Assert.True(value);
- Assert.False(_typingIndicators.TryGetValue(new Profile { Id = 4 }, out value));
- Assert.False(value);
- }
- [Test]
- public void TestContainsKey() {
- Assert.True(_typingIndicators.ContainsKey(new Profile { Id = 2 }));
- Assert.False(_typingIndicators.ContainsKey(new Profile { Id = 4 }));
- }
- [Test]
- public void TestGetKeys() {
- Assert.AreEqual(2, _typingIndicators.Keys.Count);
- Assert.True(_typingIndicators.Keys.SequenceEqual(new[] {
- new Profile { Id = 1 },
- new Profile { Id = 2 },
- }));
- Assert.True(_typingIndicators.Keys.Select(profile => profile.FullName).SequenceEqual(new[] {
- "123",
- "234",
- }));
- }
- [Test]
- public void TestGetValues() {
- Assert.AreEqual(2, _typingIndicators.Values.Count);
- Assert.True(_typingIndicators.Values.SequenceEqual(new[] {
- true,
- false,
- }));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement