public static IChangeSet <TObject, TKey> RefreshFilteredFrom <TObject, TKey>( this ChangeAwareCache <TObject, TKey> filtered, InternalCache <TObject, TKey> allData, Func <TObject, bool> predicate) { if (allData.Count == 0) { return(ChangeSet <TObject, TKey> .Empty); } foreach (var kvp in allData.KeyValues) { var exisiting = filtered.Lookup(kvp.Key); var matches = predicate(kvp.Value); if (matches) { if (!exisiting.HasValue) { filtered.Add(kvp.Value, kvp.Key); } } else { if (exisiting.HasValue) { filtered.Remove(kvp.Key); } } } return(filtered.CaptureChanges()); }
public IObservable <IChangeSet <TDestination, TKey> > Run() { return(Observable.Create <IChangeSet <TDestination, TKey> >(observer => { var locker = new object(); var shared = _source.Synchronize(locker).Publish(); //capture all items so we can apply a forced transform var cache = new InternalCache <TSource, TKey>(); var cacheLoader = shared.Subscribe(changes => cache.Clone(changes)); //create change set of items where force refresh is applied var refresher = _forceTransform.Synchronize(locker) .Select(selector => CaptureChanges(cache, selector)) .Select(changes => new ChangeSet <TSource, TKey>(changes)) .NotEmpty(); var sourceAndRefreshes = shared.Merge(refresher); //do raw transform var transform = new Transform <TDestination, TSource, TKey>(sourceAndRefreshes, _transformFactory, _exceptionCallback, true).Run(); return new CompositeDisposable(cacheLoader, transform.SubscribeSafe(observer), shared.Connect()); })); }
private static IEnumerable <Change <TSource, TKey> > CaptureChanges(InternalCache <TSource, TKey> cache, Func <TSource, TKey, bool> shouldTransform) { foreach (var kvp in cache.KeyValues) { if (shouldTransform(kvp.Value, kvp.Key)) { yield return(new Change <TSource, TKey>(ChangeReason.Refresh, kvp.Key, kvp.Value)); } } }
private void Update(InternalCache <TObject, TKey> cache, IChangeSet <TObject, TKey> updates) { IChangeSet <TObject, TKey> notifications; lock (_locker) { //update cache for the individual source cache.Clone(updates); //update combined notifications = UpdateCombined(updates); } if (notifications.Count != 0) { _updatedCallback(notifications); } }
private void RegisterForRemoval(IChangeSet <TObject, TKey> changes, InternalCache <TObject, TKey> cache) { changes.ForEach(change => { switch (change.Reason) { case ChangeReason.Update: // ReSharper disable once InconsistentlySynchronizedField change.Previous.IfHasValue(t => _removeAction(t)); break; case ChangeReason.Remove: // ReSharper disable once InconsistentlySynchronizedField _removeAction(change.Current); break; } }); cache.Clone(changes); }
public IObservable <IChangeSet <TObject, TKey> > Run() { return(Observable.Create <IChangeSet <TObject, TKey> >(observer => { var allData = new InternalCache <TObject, TKey>(); var filteredData = new ChangeAwareCache <TObject, TKey>(); Func <TObject, bool> predicate = t => false; var locker = new object(); var refresher = LatestPredicateObservable() .Synchronize(locker) .Select(p => { //set the local predicate predicate = p; //reapply filter using all data from the cache return filteredData.RefreshFilteredFrom(allData, predicate); }); var dataChanged = _source .Synchronize(locker) .Select(changes => { //maintain all data [required to re-apply filter] allData.Clone(changes); //maintain filtered data filteredData.FilterChanges(changes, predicate); //get latest changes return filteredData.CaptureChanges(); }); return refresher .Merge(dataChanged) .NotEmpty() .SubscribeSafe(observer); })); }
public IObservable <IQuery <TObject, TKey> > Run() { if (_itemChangedTrigger == null) { return(_source .Scan((InternalCache <TObject, TKey>)null, (cache, changes) => { if (cache == null) { cache = new InternalCache <TObject, TKey>(changes.Count); } cache.Clone(changes); return cache; }).Select(list => new AnonymousQuery <TObject, TKey>(list))); } return(_source.Publish(shared => { var locker = new object(); var state = new InternalCache <TObject, TKey>(); var inlineChange = shared .MergeMany(_itemChangedTrigger) .Synchronize(locker) .Select(_ => new AnonymousQuery <TObject, TKey>(state)); var sourceChanged = shared .Synchronize(locker) .Scan(state, (list, changes) => { list.Clone(changes); return list; }).Select(list => new AnonymousQuery <TObject, TKey>(list)); return sourceChanged.Merge(inlineChange); })); }
public IObservable <IChangeSet <TObject, TKey> > Run() { return(Observable.Create <IChangeSet <TObject, TKey> >(observer => { var locker = new object(); var cache = new InternalCache <TObject, TKey>(); var subscriber = _source .Synchronize(locker) .Do(changes => RegisterForRemoval(changes, cache), observer.OnError) .SubscribeSafe(observer); return Disposable.Create(() => { subscriber.Dispose(); lock (locker) { cache.Items.ForEach(t => _removeAction(t)); cache.Clear(); } }); })); }
public GroupCache(TGroupKey key) { Key = key; Cache = new InternalCache <TObject, TKey>(); }
public AnonymousQuery(InternalCache <TObject, TKey> cache) { _cache = cache.Clone(); }