[possible Bug]: ChangeAwareCache not capturing initialized data
Describe the bug 🐞
looking through the code because of something unrelated the following took me by surprise:
https://github.com/reactivemarbles/DynamicData/blob/main/src/DynamicData/Cache/ChangeAwareCache.cs#L54
initializing the ChangeAwareCache with a Dictionary and subsequently calling CaptureChanges() did not produce an initial ChangeSet!
I don't know if that might have an effect on the whole library as for example the ChangeAwareList does have code for the initial ChangeSet
Step to reproduce
just code review
Reproduction repository
https://github.com/reactivemarbles/DynamicData
Expected behavior
to send an initial ChangeSet
Screenshots 🖼️
No response
IDE
No response
Operating system
No response
Version
No response
Device
No response
DynamicData Version
No response
Additional information ℹ️
No response
That overload is intended as it is used by the source cache to ensure empty changeset when no subscribers are registered. That said it may be worth having an overload to explicitly suppress the notification when using this constructor
Maybe I shall explain how I got to this:
EFCore uses the ObservableHashSet and I wanted to use this with DynamicData. My first try was to use the ObservableCollectionEx.ToObservableChangeSet<TCollection,T>(...) overload, which wasn't very successful as that HashSet's change notifications don't really work for a list with order.
So I basically rewrote it to match a Set, maybe this is of use for the library, feel free to add it in:
public static IObservable<IChangeSet<TObject,TKey>> ToObservableChangeSet<TCollection,TObject,TKey>(this TCollection source, Func<TObject,TKey> key)
where TCollection : INotifyCollectionChanged,ISet<TObject>
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
return Observable.Create<IChangeSet<TObject,TKey>>(
observer =>
{
var data = new ChangeAwareCache<TObject, TKey>();
foreach (var item in source) data.Add(item, key(item)); // <----- this right here is necessary, because the ChangeAwareCache ctor doesn't produce an initial ChangeSet
if (data.Count > 0)
{
observer.OnNext(data.CaptureChanges());
}
return source.ObserveCollectionChanges().Scan(
data,
(cache, args) =>
{
var changes = args.EventArgs;
if (changes.NewItems is not null)
{
foreach (var item in changes.NewItems.Cast<TObject>())
{
cache.Add(item, key(item));
}
}
if (changes.OldItems is not null)
{
cache.Remove(changes.OldItems.Cast<TObject>().Select(key));
}
return cache;
}).Select(cache => cache.CaptureChanges()).SubscribeSafe(observer);
});
}