/// <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;
 }
Example #4
0
        /// <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);
        }
Example #6
0
        /// <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;
        }
Example #7
0
        /// <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));
 }