/// <summary> /// Create sequence of read operations to load data up to a specified offset. /// </summary> /// <typeparam name="TResultItem"></typeparam> /// <param name="pagedBackingStoreCollection"></param> /// <param name="offset"></param> /// <returns></returns> public static IDisposable CreateReadsUpTo <TResultItem>(this IPagedBackingStoreCollection <TResultItem> pagedBackingStoreCollection, int offset) { return(pagedBackingStoreCollection.CreateOffsetsUpTo(offset). Select(o => pagedBackingStoreCollection.ChangeSetProvider.CreateReadRequest(o)).ToObservable(). SelectMany(pr => pagedBackingStoreCollection.ChangeSetProvider.ReadPageObservable(pr)). Subscribe()); }
public StrategyBasedReadOnlyCollection(IPagedBackingStoreCollection <TItem> pagedBackingStoreCollection, ICollectionItemTouchedStrategy touchedStrategy) : base(pagedBackingStoreCollection) { Guard.NotNull(pagedBackingStoreCollection); Guard.NotNull(touchedStrategy); _touchedStrategy = touchedStrategy; }
/// <summary> /// /// </summary> /// <param name="pagedBackingStoreCollection"></param> /// <param name="bundleTicks">The number of ticks to wait before kicking of reads of data</param> /// <param name="uiScheduler">The scheduler upon which the reads are kicked off</param> /// <param name="readScheduler">The scheduler the reads are performed upon</param> public CollectionItemTouchedStrategy(IPagedBackingStoreCollection <TItem> pagedBackingStoreCollection, int bundleTicks = 0, IScheduler uiScheduler = null, IScheduler readScheduler = null) { _pagedBackingStoreCollection = pagedBackingStoreCollection; _bundleTicks = bundleTicks; _uiScheduler = uiScheduler ?? RxApp.MainThreadScheduler; _readScheduler = readScheduler ?? RxApp.TaskpoolScheduler; }
/// <summary> /// Create a collection with a specified <see cref="IPagedBackingStoreCollection{TItem}"/> and <see cref="ICollectionItemTouchedStrategy"/> /// </summary> /// <typeparam name="T"></typeparam> /// <param name="backingStoreCollection"></param> /// <param name="collectionTouchedStrategy">If not specified, <see cref="CollectionItemTouchedStrategy{TItem}"/> is used.</param> /// <returns></returns> public static ReadOnlyCollectionFromBackingStore <T> Create <T>(IPagedBackingStoreCollection <T> backingStoreCollection, ICollectionItemTouchedStrategy collectionTouchedStrategy = null) where T : class { // the strategy to request page loads in the backing store var touched = collectionTouchedStrategy ?? new CollectionItemTouchedStrategy <T>(backingStoreCollection); // the actual list we will bind to... var collection = new StrategyBasedReadOnlyCollection <T>(backingStoreCollection, touched); return(collection); }
/// <summary> /// Return /// </summary> /// <typeparam name="TResultItem"></typeparam> /// <param name="pagedBackingStoreCollection"></param> /// <param name="readOffset"></param> /// <returns></returns> public static IEnumerable <int> CreateOffsets <TResultItem>( this IPagedBackingStoreCollection <TResultItem> pagedBackingStoreCollection, int readOffset) { var maxPageSize = pagedBackingStoreCollection.ChangeSetProvider.MaxPageSize; var offsetsToRead = new HashSet <int>(); // work out the aligned base that this falls into) // we potentially align upwards to force the read of the page following, ensuring a contiguous run. var alignedOffset = (maxPageSize == int.MaxValue) ? readOffset : ((int)Math.Round(((float)readOffset) / maxPageSize)) * maxPageSize; // if don't have a total, or we are below the total amount then enqueue the read... if (!pagedBackingStoreCollection.Total.HasValue || alignedOffset < pagedBackingStoreCollection.Total) { offsetsToRead.Add(alignedOffset); } return(offsetsToRead); }
/// <summary> /// Create a paged collection which wrappers a backing store. /// </summary> /// <param name="pagedBackingStoreCollection"></param> public ReadOnlyCollectionFromBackingStore(IPagedBackingStoreCollection <TItem> pagedBackingStoreCollection) { Guard.NotNull(pagedBackingStoreCollection); // Setup the subscription to pass along changes to those that are interested... var subscription = pagedBackingStoreCollection. ChangeSetProvider. Changes. Subscribe(changes => { // need to raise the appropriate collection changed things... // as changes an observable can provide... foreach (var change in changes) { switch (change.Reason) { case ListChangeReason.Add: CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, change.Item.Current, change.Item.CurrentIndex)); break; case ListChangeReason.AddRange: CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, change.Range)); break; case ListChangeReason.Remove: if (change.Range != null) { CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, change.Range, change.Range.Index)); } else { CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, change.Item.Current, change.Item.CurrentIndex)); } break; case ListChangeReason.Replace: { var @event = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, change.Item.Current, change.Item.Previous.Value, change.Item.CurrentIndex); CollectionChanged?.Invoke(this, @event); break; } case ListChangeReason.Clear: CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); break; case ListChangeReason.Moved: CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, change.Item.Current, change.Item.CurrentIndex, change.Item.PreviousIndex)); break; } } }); _changeSetDisposable.Disposable = subscription; _backingStoreCollection = pagedBackingStoreCollection; }
/// <summary> /// Create a collection backed from a <see cref="SourceCache{TObject,TKey}"/> /// </summary> /// <typeparam name="T">The type stored in the collection</typeparam> /// <typeparam name="TKey">The key type</typeparam> /// <param name="readPageObservable">The observable which provides the pages of content</param> /// <param name="keySelector">The key selector</param> /// <param name="maxPageSize">The maximum size of page to be read, the default being 10</param> /// <param name="onException">The observable to be used when errors on paging are seen. Null will result in the default behavior, which is fail.</param> /// <param name="collectionTouchedStrategy">The strategy to be used when items in a collection are touched. If null <see cref="CollectionItemTouchedStrategy{TItem}"/> is used.</param> /// <param name="backingStoreCollection">The store to be used to back the collection. If null <see cref="SimpleBackingStoreCollection{TItem}" /> is used</param> /// <returns></returns> public static ReadOnlyCollectionFromBackingStore <T> FromSourceCachePager <T, TKey>(Func <PageReadRequest, IObservable <PageReadResult <T> > > readPageObservable, Func <T, TKey> keySelector, int maxPageSize = 10, Func <PageReadRequest, Exception, IObservable <bool> > onException = null, ICollectionItemTouchedStrategy collectionTouchedStrategy = null, IPagedBackingStoreCollection <T> backingStoreCollection = null) where T : class { var provider = SourceCacheBacked <T, TKey> .FromObservable(readPageObservable, keySelector, maxPageSize, onException); return(Create(provider, collectionTouchedStrategy)); }
/// <summary> /// Create a collection with a null touch strategy. /// </summary> /// <param name="pagedBackingStoreCollection"></param> public StrategyBasedReadOnlyCollection(IPagedBackingStoreCollection <TItem> pagedBackingStoreCollection) : this(pagedBackingStoreCollection, NullCollectionItemTouchedStrategy.Instance) { }
/// <summary> /// Create an enumeration of offsets required to read up to a specified offset. /// </summary> /// <typeparam name="TResultItem"></typeparam> /// <param name="pagedBackingStoreCollection"></param> /// <param name="offset"></param> /// <returns></returns> public static IEnumerable <int> CreateOffsetsUpTo <TResultItem>( this IPagedBackingStoreCollection <TResultItem> pagedBackingStoreCollection, int offset) { return(pagedBackingStoreCollection.ChangeSetProvider.CreateOffsetsUpTo(pagedBackingStoreCollection.Total, offset)); }