Skip to content

Commit

Permalink
Add overload of Cache.AddOrUpdate(IEnumerable) which accepts a compar…
Browse files Browse the repository at this point in the history
…er. Fixes #553 (#560)
  • Loading branch information
RolandPheasant authored Feb 14, 2022
1 parent 7e56818 commit 8459c58
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 12 deletions.
9 changes: 8 additions & 1 deletion src/DynamicData/Cache/ISourceUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ public interface ISourceUpdater<TObject, TKey> : ICacheUpdater<TObject, TKey>
/// <param name="items">The items.</param>
void AddOrUpdate(IEnumerable<TObject> items);

/// <summary>
/// Adds or changes the specified items.
/// </summary>
/// <param name="items">The items.</param>
/// <param name="comparer">The comparer.</param>
void AddOrUpdate(IEnumerable<TObject> items, IEqualityComparer<TObject> comparer);

/// <summary>
/// Adds or updates the item.
/// </summary>
Expand Down Expand Up @@ -86,4 +93,4 @@ public interface ISourceUpdater<TObject, TKey> : ICacheUpdater<TObject, TKey>
/// <param name="item">The item.</param>
void Remove(TObject item);
}
}
}
49 changes: 39 additions & 10 deletions src/DynamicData/Cache/Internal/CacheUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,8 @@ public CacheUpdater(Dictionary<TKey, TObject> data, Func<TObject, TKey>? keySele

public void AddOrUpdate(IEnumerable<TObject> items)
{
if (items is null)
{
throw new ArgumentNullException(nameof(items));
}

if (_keySelector is null)
{
throw new KeySelectorException("A key selector must be specified");
}
if (items is null) throw new ArgumentNullException(nameof(items));
if (_keySelector is null) throw new KeySelectorException("A key selector must be specified");

if (items is IList<TObject> list)
{
Expand All @@ -71,6 +64,42 @@ public void AddOrUpdate(IEnumerable<TObject> items)
}
}

public void AddOrUpdate(IEnumerable<TObject> items, IEqualityComparer<TObject> comparer)
{
if (items is null) throw new ArgumentNullException(nameof(items));
if (comparer is null) throw new ArgumentNullException(nameof(comparer));
if (_keySelector is null) throw new KeySelectorException("A key selector must be specified");

void AddOrUpdateImpl(TObject item)
{
var key = _keySelector!(item);
var oldItem = _cache.Lookup(key);

if (oldItem.HasValue)
{
if (comparer.Equals(oldItem.Value, item)) return;

_cache.AddOrUpdate(item, key);
}
else
{
_cache.AddOrUpdate(item, key);
}
}

if (items is IList<TObject> list)
{
// zero allocation enumerator
foreach (var item in EnumerableIList.Create(list))
AddOrUpdateImpl(item);
}
else
{
foreach (var item in items)
AddOrUpdateImpl(item);
}
}

public void AddOrUpdate(TObject item)
{
if (_keySelector is null)
Expand Down Expand Up @@ -395,4 +424,4 @@ public void Update(IChangeSet<TObject, TKey> changes)
_cache.Clone(changes);
}
}
}
}
24 changes: 23 additions & 1 deletion src/DynamicData/Cache/ObservableCacheEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,28 @@ public static void AddOrUpdate<TObject, TKey>(this ISourceCache<TObject, TKey> s
source.Edit(updater => updater.AddOrUpdate(items));
}

/// <summary>
/// <summary>
/// Adds or updates the cache with the specified items.
/// </summary>
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The source.</param>
/// <param name="items">The items.</param>
/// <param name="equalityComparer">The equality comparer used to determine whether a new item is the same as an existing cached item.</param>
/// <exception cref="System.ArgumentNullException">source.</exception>
public static void AddOrUpdate<TObject, TKey>(this ISourceCache<TObject, TKey> source, IEnumerable<TObject> items, IEqualityComparer<TObject> equalityComparer)
where TKey : notnull
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}

source.Edit(updater => updater.AddOrUpdate(items, equalityComparer));
}

/// <summary>
/// Removes the specified key from the cache.
/// If the item is not contained in the cache then the operation does nothing.
Expand Down Expand Up @@ -5648,4 +5670,4 @@ private static IObservable<bool> TrueFor<TObject, TKey, TValue>(this IObservable
return new TrueFor<TObject, TKey, TValue>(source, observableSelector, collectionMatcher).Run();
}
}
}
}

0 comments on commit 8459c58

Please sign in to comment.