コード例 #1
0
        /// <summary>
        /// Creates an observable list from a specified cancellable asynchronous Subscribe method. The CancellationToken passed to the asynchronous Subscribe method is tied to the returned disposable subscription, allowing best-effort cancellation.
        /// </summary>
        /// <typeparam name="T">The type of the elements contained in the observable list</typeparam>
        /// <param name="subscribe">  Implementation of the resulting observable list's Subscribe method. </param>
        /// <returns>The observable list with the specified implementation for the Subscribe method.</returns>
        public static IObservable <IChangeSet <T> > Create <T>(Func <ISourceList <T>, CancellationToken, Task <Action> > subscribe)
        {
            if (subscribe == null)
            {
                throw new ArgumentNullException(nameof(subscribe));
            }

            return(Observable.Create <IChangeSet <T> >(async(observer, ct) =>
            {
                var list = new SourceList <T>();
                Action disposeAction = null;

                try
                {
                    disposeAction = await subscribe(list, ct);
                }
                catch (Exception e)
                {
                    observer.OnError(e);
                }

                return new CompositeDisposable(list.Connect().SubscribeSafe(observer), list, Disposable.Create(() =>
                {
                    observer.OnCompleted();
                    disposeAction?.Invoke();
                }));
            }));
        }
コード例 #2
0
        /// <summary>
        /// Creates an observable list from a specified Subscribe method implementation.
        /// </summary>
        /// <typeparam name="T">The type of the elements contained in the observable list</typeparam>
        /// <param name="subscribe">  Implementation of the resulting observable list's Subscribe method. </param>
        /// <returns>The observable list with the specified implementation for the Subscribe method.</returns>
        public static IObservable <IChangeSet <T> > Create <T>(Func <ISourceList <T>, IDisposable> subscribe)
        {
            if (subscribe == null)
            {
                throw new ArgumentNullException(nameof(subscribe));
            }

            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                var list = new SourceList <T>();
                IDisposable disposeAction = null;

                try
                {
                    disposeAction = subscribe(list);
                }
                catch (Exception e)
                {
                    observer.OnError(e);
                }

                return new CompositeDisposable(list.Connect().SubscribeSafe(observer), list, Disposable.Create(() =>
                {
                    observer.OnCompleted();
                    disposeAction?.Dispose();
                }));
            }));
        }
コード例 #3
0
        /// <summary>
        /// Creates an observable list from a specified cancellable asynchronous Subscribe method. The CancellationToken passed to the asynchronous Subscribe method is tied to the returned disposable subscription, allowing best-effort cancellation.
        /// </summary>
        /// <typeparam name="T">The type of the elements contained in the observable list.</typeparam>
        /// <param name="subscribe">  Implementation of the resulting observable list's Subscribe method. </param>
        /// <returns>The observable list with the specified implementation for the Subscribe method.</returns>
        public static IObservable <IChangeSet <T> > Create <T>(Func <ISourceList <T>, CancellationToken, Task <IDisposable> > subscribe)
        {
            if (subscribe is null)
            {
                throw new ArgumentNullException(nameof(subscribe));
            }

            return(Observable.Create <IChangeSet <T> >(
                       async(observer, ct) =>
            {
                var list = new SourceList <T>();
                IDisposable?disposeAction = null;
                SingleAssignmentDisposable actionDisposable = new();

                try
                {
                    disposeAction = await subscribe(list, ct).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    observer.OnError(e);
                }

                return new CompositeDisposable(
                    list.Connect().SubscribeSafe(observer),
                    list,
                    actionDisposable,
                    Disposable.Create(
                        () =>
                {
                    observer.OnCompleted();
                    disposeAction?.Dispose();
                }));
            }));
        }
コード例 #4
0
        /// <summary>
        /// Creates an observable list from a specified asynchronous Subscribe method.
        /// </summary>
        /// <typeparam name="T">The type of the elements contained in the observable list</typeparam>
        /// <param name="subscribe">  Implementation of the resulting observable list's Subscribe method. </param>
        /// <returns>The observable list with the specified implementation for the Subscribe method.</returns>
        public static IObservable <IChangeSet <T> > Create <T>(Func <ISourceList <T>, Task> subscribe)
        {
            if (subscribe == null)
            {
                throw new ArgumentNullException(nameof(subscribe));
            }

            return(Observable.Create <IChangeSet <T> >(async observer =>
            {
                var list = new SourceList <T>();

                try
                {
                    await subscribe(list).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    observer.OnError(e);
                }

                return new CompositeDisposable(list.Connect().SubscribeSafe(observer), list, Disposable.Create(observer.OnCompleted));
            }));
        }
コード例 #5
0
        public static IObservable <IChangeSet <TObject> > DelayRemove <TObject>(this IObservable <IChangeSet <TObject> > source,
                                                                                TimeSpan delayPeriod, Action <TObject> onDefer)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (onDefer == null)
            {
                throw new ArgumentNullException(nameof(onDefer));
            }

            return(Observable.Create <IChangeSet <TObject> >(observer =>
            {
                var removed = new [] { ListChangeReason.Remove, ListChangeReason.Clear, ListChangeReason.RemoveRange };

                var localList = new SourceList <TObject>();

                var locker = new object();
                var shared = source.Synchronize(locker).Publish();

                var notRemoved = shared.WhereReasonsAreNot(removed)
                                 .Subscribe(changes =>
                {
                    localList.Edit(innerList =>
                    {
                        changes.ForEach(change =>
                        {
                            switch (change.Reason)
                            {
                            case ListChangeReason.Add:
                                innerList.Add(change.Item.Current);
                                break;

                            case ListChangeReason.AddRange:
                                change.Range.ForEach(innerList.Add);
                                break;

                            case ListChangeReason.Replace:
                                innerList.Replace(change.Item.Previous.Value, change.Item.Current);
                                break;
                            }
                        });
                    });
                });

                //when removed,invoke call back
                var removes = shared.WhereReasonsAre(removed)
                              .ForEachItemChange(change => onDefer(change.Current))
                              .Delay(delayPeriod)
                              .Synchronize(locker)
                              .Subscribe(changes =>
                {
                    //flatten removes into a single enumerable
                    var toRemove = changes.SelectMany(change =>
                    {
                        return change.Type == ChangeType.Item ? new[] { change.Item.Current } : change.Range.Select(t => t);
                    }).ToArray();
                    //remove in one hit
                    localList.RemoveMany(toRemove);
                });

                var subscriber = localList.Connect().SubscribeSafe(observer);
                return new CompositeDisposable(subscriber, removes, notRemoved, shared.Connect());
            }));
        }