예제 #1
0
        public IObservable <IChangeSet <T> > Run()
        {
            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                var locker = new object();
                var orginal = new ChangeAwareList <T>();
                var target = new ChangeAwareList <T>();

                var changed = _source.Synchronize(locker).Select(changes =>
                {
                    if (_resetThreshold > 1)
                    {
                        orginal.Clone(changes);
                    }

                    return changes.TotalChanges > _resetThreshold && _comparer != null ? Reset(orginal, target) : Process(target, changes);
                });
                var resort = _resort.Synchronize(locker).Select(changes => Reorder(target));
                var changeComparer = _comparerObservable.Synchronize(locker).Select(comparer => ChangeComparer(target, comparer));

                return changed.Merge(resort).Merge(changeComparer)
                .Where(changes => changes.Count != 0)
                .SubscribeSafe(observer);
            }));
        }
예제 #2
0
        public Continuation <IChangeSet <T> > Write(IChangeSet <T> changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException(nameof(changes));
            }
            IChangeSet <T> result;

            lock (_locker)
            {
                try
                {
                    _data.Clone(changes);
                    result = _data.CaptureChanges();
                }
                catch (Exception ex)
                {
                    return(new Continuation <IChangeSet <T> >(ex));
                }
            }
            return(new Continuation <IChangeSet <T> >(result));
        }
예제 #3
0
        private IChangeSet <T> ProcessImpl(ChangeAwareList <T> target, IChangeSet <T> changes)
        {
            if (_comparer == null)
            {
                target.Clone(changes);
                return(target.CaptureChanges());
            }

            foreach (var change in changes)
            {
                switch (change.Reason)
                {
                case ListChangeReason.Add:
                {
                    var current = change.Item.Current;
                    Insert(target, current);
                    break;
                }

                case ListChangeReason.AddRange:
                {
                    var ordered = change.Range.OrderBy(t => t, _comparer).ToList();
                    if (target.Count == 0)
                    {
                        target.AddRange(ordered);
                    }
                    else
                    {
                        ordered.ForEach(item => Insert(target, item));
                    }
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var current = change.Item.Current;
                    //TODO: check whether an item should stay in the same position
                    //i.e. update and move
                    Remove(target, change.Item.Previous.Value);
                    Insert(target, current);
                    break;
                }

                case ListChangeReason.Remove:
                {
                    var current = change.Item.Current;
                    Remove(target, current);
                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    target.RemoveMany(change.Range);
                    break;
                }

                case ListChangeReason.Clear:
                {
                    target.Clear();
                    break;
                }
                }
            }
            return(target.CaptureChanges());
        }