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
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Verifies that a new multi dictionary based on a read-only dictionary is
|
||||
/// also read-only
|
||||
|
@ -116,6 +130,15 @@ namespace Nuclex.Support.Collections {
|
|||
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>
|
||||
/// Ensures that its possible to remove values individually without affecting
|
||||
/// other values stored under the same key
|
||||
|
@ -150,10 +173,39 @@ namespace Nuclex.Support.Collections {
|
|||
dictionary.Add(10, "zehn");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <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
|
||||
|
|
|
@ -333,11 +333,34 @@ namespace Nuclex.Support.Collections {
|
|||
|
||||
ICollection<TValue> 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 {
|
||||
currentValues = new ValueList(this);
|
||||
this.typedDictionary.Add(key, currentValues);
|
||||
}
|
||||
|
||||
foreach(TValue addedValue in value) {
|
||||
currentValues.Add(addedValue);
|
||||
|
@ -345,6 +368,7 @@ namespace Nuclex.Support.Collections {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Inserts an item into the dictionary</summary>
|
||||
/// <param name="key">Key under which to add the new item</param>
|
||||
|
@ -420,6 +444,13 @@ namespace Nuclex.Support.Collections {
|
|||
/// <param name="item">Item that has been removed from the collection</param>
|
||||
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>
|
||||
protected virtual void OnClearing() { }
|
||||
|
||||
|
|
|
@ -31,12 +31,40 @@ using NMock;
|
|||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
#if false
|
||||
/// <summary>Unit Test for the observable set wrapper</summary>
|
||||
[TestFixture]
|
||||
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
|
||||
|
||||
|
|
|
@ -82,7 +82,11 @@ namespace Nuclex.Support.Collections {
|
|||
/// True if the element was added, false if it was already contained in the set
|
||||
/// </returns>
|
||||
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>
|
||||
|
|
Loading…
Reference in New Issue
Block a user