MultiDictionary wasn't firing 'removed' events when an entire set of values is replaced - fixed, but not unit-tested yet; added more unit tests to the ObservableSet class; ObservableSet was not firing the 'added' event - fixed
git-svn-id: file:///srv/devel/repo-conversion/nusu@260 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
0195b34289
commit
b37c4a757c
|
@ -41,6 +41,20 @@ namespace Nuclex.Support.Collections {
|
||||||
Assert.IsNotNull(dictionary); // nonsense, prevents compiler warning
|
Assert.IsNotNull(dictionary); // nonsense, prevents compiler warning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that the count is initialized correctly when building
|
||||||
|
/// a multi dictionary from a dictionary of value collections.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CountIsCalculatedIfInitializedFromDictionary() {
|
||||||
|
var contents = new Dictionary<int, ICollection<string>>();
|
||||||
|
contents.Add(1, new List<string>(new string[] { "one", "eins" }));
|
||||||
|
contents.Add(2, new List<string>(new string[] { "two", "zwei" }));
|
||||||
|
|
||||||
|
var multiDictionary = new MultiDictionary<int, string>(contents);
|
||||||
|
Assert.AreEqual(4, multiDictionary.Count);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies that a new multi dictionary based on a read-only dictionary is
|
/// Verifies that a new multi dictionary based on a read-only dictionary is
|
||||||
/// also read-only
|
/// also read-only
|
||||||
|
@ -116,6 +130,15 @@ namespace Nuclex.Support.Collections {
|
||||||
Assert.AreEqual(1, dictionary.CountValues(30));
|
Assert.AreEqual(1, dictionary.CountValues(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that counting the values of a non-existing key returns 0
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CountingValuesOfNonExistentKeyReturnsNull() {
|
||||||
|
var dictionary = new MultiDictionary<int, string>();
|
||||||
|
Assert.AreEqual(0, dictionary.CountValues(1));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ensures that its possible to remove values individually without affecting
|
/// Ensures that its possible to remove values individually without affecting
|
||||||
/// other values stored under the same key
|
/// other values stored under the same key
|
||||||
|
@ -150,10 +173,39 @@ namespace Nuclex.Support.Collections {
|
||||||
dictionary.Add(10, "zehn");
|
dictionary.Add(10, "zehn");
|
||||||
|
|
||||||
Assert.AreEqual(2, dictionary.Count);
|
Assert.AreEqual(2, dictionary.Count);
|
||||||
var collectionOfCollections = (ICollection<KeyValuePair<int, ICollection<string>>>)dictionary;
|
var collectionOfCollections =
|
||||||
|
(ICollection<KeyValuePair<int, ICollection<string>>>)dictionary;
|
||||||
Assert.AreEqual(1, collectionOfCollections.Count);
|
Assert.AreEqual(1, collectionOfCollections.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that the multi dictionary can be tested for containment of a specific value
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void ContainmentCanBeTested() {
|
||||||
|
var dictionary = new MultiDictionary<int, string>();
|
||||||
|
dictionary.Add(10, "ten");
|
||||||
|
dictionary.Add(10, "zehn");
|
||||||
|
|
||||||
|
Assert.IsTrue(dictionary.Contains(new KeyValuePair<int, string>(10, "ten")));
|
||||||
|
Assert.IsTrue(dictionary.Contains(new KeyValuePair<int, string>(10, "zehn")));
|
||||||
|
Assert.IsFalse(dictionary.Contains(new KeyValuePair<int, string>(10, "dix")));
|
||||||
|
Assert.IsFalse(dictionary.Contains(new KeyValuePair<int, string>(20, "ten")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that the multi dictionary can be tested for containment of a specific key
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void KeyContainmentCanBeTested() {
|
||||||
|
var dictionary = new MultiDictionary<int, string>();
|
||||||
|
dictionary.Add(10, "ten");
|
||||||
|
dictionary.Add(10, "zehn");
|
||||||
|
|
||||||
|
Assert.IsTrue(dictionary.ContainsKey(10));
|
||||||
|
Assert.IsFalse(dictionary.ContainsKey(20));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Nuclex.Support.Collections
|
} // namespace Nuclex.Support.Collections
|
||||||
|
|
|
@ -333,15 +333,39 @@ namespace Nuclex.Support.Collections {
|
||||||
|
|
||||||
ICollection<TValue> currentValues;
|
ICollection<TValue> currentValues;
|
||||||
if(this.typedDictionary.TryGetValue(key, out currentValues)) {
|
if(this.typedDictionary.TryGetValue(key, out currentValues)) {
|
||||||
currentValues.Clear();
|
ValueList currentValueList = (ValueList)currentValues;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
foreach(TValue addedValue in value) {
|
||||||
|
if(index < currentValueList.Count) {
|
||||||
|
TValue original = currentValueList[index];
|
||||||
|
currentValueList[index] = addedValue;
|
||||||
|
OnReplaced(
|
||||||
|
new KeyValuePair<TKey, TValue>(key, original),
|
||||||
|
new KeyValuePair<TKey, TValue>(key, addedValue)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
currentValueList.Add(addedValue);
|
||||||
|
OnAdded(new KeyValuePair<TKey, TValue>(key, addedValue));
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = currentValueList.Count;
|
||||||
|
while(count > index) {
|
||||||
|
--count;
|
||||||
|
TValue removedValue = currentValueList[count];
|
||||||
|
currentValueList.RemoveAt(count);
|
||||||
|
OnRemoved(new KeyValuePair<TKey, TValue>(key, removedValue));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
currentValues = new ValueList(this);
|
currentValues = new ValueList(this);
|
||||||
this.typedDictionary.Add(key, currentValues);
|
this.typedDictionary.Add(key, currentValues);
|
||||||
}
|
|
||||||
|
|
||||||
foreach(TValue addedValue in value) {
|
foreach(TValue addedValue in value) {
|
||||||
currentValues.Add(addedValue);
|
currentValues.Add(addedValue);
|
||||||
OnAdded(new KeyValuePair<TKey, TValue>(key, addedValue));
|
OnAdded(new KeyValuePair<TKey, TValue>(key, addedValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,6 +444,13 @@ namespace Nuclex.Support.Collections {
|
||||||
/// <param name="item">Item that has been removed from the collection</param>
|
/// <param name="item">Item that has been removed from the collection</param>
|
||||||
protected virtual void OnRemoved(KeyValuePair<TKey, TValue> item) { }
|
protected virtual void OnRemoved(KeyValuePair<TKey, TValue> item) { }
|
||||||
|
|
||||||
|
/// <summary>Fires the 'ItemReplaced' event</summary>
|
||||||
|
/// <param name="oldItem">Item that was replaced in the collection</param>
|
||||||
|
/// <param name="newItem">Item that the original was replaced by</param>
|
||||||
|
protected virtual void OnReplaced(
|
||||||
|
KeyValuePair<TKey, TValue> oldItem, KeyValuePair<TKey, TValue> newItem
|
||||||
|
) { }
|
||||||
|
|
||||||
/// <summary>Fires the 'Clearing' event</summary>
|
/// <summary>Fires the 'Clearing' event</summary>
|
||||||
protected virtual void OnClearing() { }
|
protected virtual void OnClearing() { }
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,40 @@ using NMock;
|
||||||
|
|
||||||
namespace Nuclex.Support.Collections {
|
namespace Nuclex.Support.Collections {
|
||||||
|
|
||||||
#if false
|
|
||||||
/// <summary>Unit Test for the observable set wrapper</summary>
|
/// <summary>Unit Test for the observable set wrapper</summary>
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
internal class ObservableSetTest {
|
internal class ObservableSetTest {
|
||||||
|
|
||||||
|
#region interface IObservableCollectionSubscriber<TItem>
|
||||||
|
|
||||||
|
public interface IObservableCollectionSubscriber<TItem> {
|
||||||
|
|
||||||
|
/// <summary>Raised when an item has been added to the collection</summary>
|
||||||
|
event EventHandler<ItemEventArgs<TItem>> ItemAdded;
|
||||||
|
/// <summary>Raised when an item is removed from the collection</summary>
|
||||||
|
event EventHandler<ItemEventArgs<TItem>> ItemRemoved;
|
||||||
|
/// <summary>Raised when an item is replaced in the collection</summary>
|
||||||
|
event EventHandler<ItemReplaceEventArgs<TItem>> ItemReplaced;
|
||||||
|
/// <summary>Raised when the collection is about to be cleared</summary>
|
||||||
|
event EventHandler Clearing;
|
||||||
|
/// <summary>Raised when the collection has been cleared</summary>
|
||||||
|
event EventHandler Cleared;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // interface IObservableCollectionSubscriber<TItem>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that the observable set has a default constructor
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void HasDefaultConstructor() {
|
||||||
|
Assert.IsNotNull(new ObservableSet<int>());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Nuclex.Support.Collections
|
} // namespace Nuclex.Support.Collections
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,11 @@ namespace Nuclex.Support.Collections {
|
||||||
/// True if the element was added, false if it was already contained in the set
|
/// True if the element was added, false if it was already contained in the set
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public bool Add(TItem item) {
|
public bool Add(TItem item) {
|
||||||
return this.set.Add(item);
|
bool wasAdded = this.set.Add(item);
|
||||||
|
if(wasAdded) {
|
||||||
|
OnAdded(item);
|
||||||
|
}
|
||||||
|
return wasAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Removes all elements that are contained in the collection</summary>
|
/// <summary>Removes all elements that are contained in the collection</summary>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user