示例#1
0
        private void Process(ChangeAwareList <T> filtered, IChangeSet <T> changes)
        {
            foreach (var item in changes)
            {
                switch (item.Reason)
                {
                case ListChangeReason.Add:
                {
                    var change = item.Item;
                    if (_predicate(change.Current))
                    {
                        filtered.Add(change.Current);
                    }

                    break;
                }

                case ListChangeReason.AddRange:
                {
                    var matches = item.Range.Where(t => _predicate(t)).ToList();
                    filtered.AddRange(matches);
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var change = item.Item;
                    var match  = _predicate(change.Current);
                    if (match)
                    {
                        filtered.ReplaceOrAdd(change.Previous.Value, change.Current);
                    }
                    else
                    {
                        filtered.Remove(change.Previous.Value);
                    }

                    break;
                }

                case ListChangeReason.Remove:
                {
                    filtered.Remove(item.Item.Current);
                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    filtered.RemoveMany(item.Range);
                    break;
                }

                case ListChangeReason.Clear:
                {
                    filtered.ClearOrRemoveMany(item);
                    break;
                }
                }
            }
        }
示例#2
0
        private void Transform(ChangeAwareList <TransformedItemContainer> transformed, IChangeSet <TSource> changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException(nameof(changes));
            }

            foreach (var item in changes)
            {
                switch (item.Reason)
                {
                case ListChangeReason.Add:
                {
                    var change = item.Item;
                    if (change.CurrentIndex < 0 | change.CurrentIndex >= transformed.Count)
                    {
                        transformed.Add(_containerFactory(change.Current, Optional <TDestination> .None, transformed.Count));
                    }
                    else
                    {
                        var converted = _containerFactory(change.Current, Optional <TDestination> .None, change.CurrentIndex);
                        transformed.Insert(change.CurrentIndex, converted);
                    }
                    break;
                }

                case ListChangeReason.AddRange:
                {
                    var startIndex = item.Range.Index < 0 ? transformed.Count : item.Range.Index;

                    transformed.AddOrInsertRange(item.Range
                                                 .Select((t, idx) => _containerFactory(t, Optional <TDestination> .None, idx + startIndex)),
                                                 item.Range.Index);

                    break;
                }

                case ListChangeReason.Refresh:
                {
                    if (_transformOnRefresh)
                    {
                        var change = item.Item;
                        Optional <TDestination> previous = transformed[change.CurrentIndex].Destination;
                        var refreshed = _containerFactory(change.Current, previous, change.CurrentIndex);

                        transformed[change.CurrentIndex] = refreshed;
                    }
                    else
                    {
                        transformed.RefreshAt(item.Item.CurrentIndex);
                    }
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var change = item.Item;
                    Optional <TDestination> previous = transformed[change.PreviousIndex].Destination;
                    if (change.CurrentIndex == change.PreviousIndex)
                    {
                        transformed[change.CurrentIndex] = _containerFactory(change.Current, previous, change.CurrentIndex);
                    }
                    else
                    {
                        transformed.RemoveAt(change.PreviousIndex);
                        transformed.Insert(change.CurrentIndex, _containerFactory(change.Current, Optional <TDestination> .None, change.CurrentIndex));
                    }

                    break;
                }

                case ListChangeReason.Remove:
                {
                    var  change   = item.Item;
                    bool hasIndex = change.CurrentIndex >= 0;

                    if (hasIndex)
                    {
                        transformed.RemoveAt(change.CurrentIndex);
                    }
                    else
                    {
                        var toRemove = transformed.FirstOrDefault(t => ReferenceEquals(t.Source, change.Current));

                        if (toRemove != null)
                        {
                            transformed.Remove(toRemove);
                        }
                    }

                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    if (item.Range.Index >= 0)
                    {
                        transformed.RemoveRange(item.Range.Index, item.Range.Count);
                    }
                    else
                    {
                        var toRemove = transformed.Where(t => item.Range.Any(current => ReferenceEquals(t.Source, current)));
                        transformed.RemoveMany(toRemove);
                    }

                    break;
                }

                case ListChangeReason.Clear:
                {
                    //i.e. need to store transformed reference so we can correctly clear
                    var toClear = new Change <TransformedItemContainer>(ListChangeReason.Clear, transformed);
                    transformed.ClearOrRemoveMany(toClear);

                    break;
                }

                case ListChangeReason.Moved:
                {
                    var  change   = item.Item;
                    bool hasIndex = change.CurrentIndex >= 0;
                    if (!hasIndex)
                    {
                        throw new UnspecifiedIndexException("Cannot move as an index was not specified");
                    }

                    transformed.Move(change.PreviousIndex, change.CurrentIndex);
                    break;
                }
                }
            }
        }
示例#3
0
        private void Transform(ChangeAwareList <TransformedItemContainer> transformed, IChangeSet <TSource> changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException(nameof(changes));
            }

            transformed.EnsureCapacityFor(changes);

            foreach (var item in changes)
            {
                switch (item.Reason)
                {
                case ListChangeReason.Add:
                {
                    var change = item.Item;
                    if (change.CurrentIndex < 0 | change.CurrentIndex >= transformed.Count)
                    {
                        transformed.Add(_containerFactory(change.Current));
                    }
                    else
                    {
                        transformed.Insert(change.CurrentIndex, _containerFactory(change.Current));
                    }
                    break;
                }

                case ListChangeReason.AddRange:
                {
                    transformed.AddOrInsertRange(item.Range.Select(_containerFactory), item.Range.Index);
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var change = item.Item;
                    if (change.CurrentIndex == change.PreviousIndex)
                    {
                        transformed[change.CurrentIndex] = _containerFactory(change.Current);
                    }
                    else
                    {
                        transformed.RemoveAt(change.PreviousIndex);
                        transformed.Insert(change.CurrentIndex, _containerFactory(change.Current));
                    }

                    break;
                }

                case ListChangeReason.Remove:
                {
                    var  change   = item.Item;
                    bool hasIndex = change.CurrentIndex >= 0;

                    if (hasIndex)
                    {
                        transformed.RemoveAt(item.Item.CurrentIndex);
                    }
                    else
                    {
                        var toremove = transformed.FirstOrDefault(t => ReferenceEquals(t.Source, t));

                        if (toremove != null)
                        {
                            transformed.Remove(toremove);
                        }
                    }

                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    if (item.Range.Index >= 0)
                    {
                        transformed.RemoveRange(item.Range.Index, item.Range.Count);
                    }
                    else
                    {
                        var toremove = transformed.Where(t => ReferenceEquals(t.Source, t)).ToArray();
                        transformed.RemoveMany(toremove);
                    }

                    break;
                }

                case ListChangeReason.Clear:
                {
                    //i.e. need to store transformed reference so we can correctly clear
                    var toClear = new Change <TransformedItemContainer>(ListChangeReason.Clear, transformed);
                    transformed.ClearOrRemoveMany(toClear);

                    break;
                }

                case ListChangeReason.Moved:
                {
                    var  change   = item.Item;
                    bool hasIndex = change.CurrentIndex >= 0;
                    if (!hasIndex)
                    {
                        throw new UnspecifiedIndexException("Cannot move as an index was not specified");
                    }

                    var collection = transformed as IExtendedList <TransformedItemContainer>;
                    if (collection != null)
                    {
                        collection.Move(change.PreviousIndex, change.CurrentIndex);
                    }
                    else
                    {
                        var current = transformed[change.PreviousIndex];
                        transformed.RemoveAt(change.PreviousIndex);
                        transformed.Insert(change.CurrentIndex, current);
                    }
                    break;
                }
                }
            }
        }
示例#4
0
        private void Process(ChangeAwareList <ItemWithMatch> filtered, IChangeSet <ItemWithMatch> changes)
        {
            //Maintain all items as well as filtered list. This enables us to a) requery when the predicate changes b) check the previous state when Refresh is called
            foreach (var item in changes)
            {
                switch (item.Reason)
                {
                case ListChangeReason.Add:
                {
                    var change = item.Item;
                    if (change.Current.IsMatch)
                    {
                        filtered.Add(change.Current);
                    }
                    break;
                }

                case ListChangeReason.AddRange:
                {
                    var matches = item.Range.Where(t => t.IsMatch).ToList();
                    filtered.AddRange(matches);
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var change   = item.Item;
                    var match    = change.Current.IsMatch;
                    var wasMatch = item.Item.Current.WasMatch;
                    if (match)
                    {
                        if (wasMatch)
                        {
                            //an update, so get the latest index and pass the index up the chain
                            var previous = filtered.Select(x => x.Item)
                                           .IndexOfOptional(change.Previous.Value.Item, ReferenceEqualityComparer <T> .Instance)
                                           .ValueOrThrow(() => new InvalidOperationException($"Cannot find index of {typeof(T).Name} -> {change.Previous.Value}. Expected to be in the list"));

                            //replace inline
                            filtered[previous.Index] = change.Current;
                        }
                        else
                        {
                            filtered.Add(change.Current);
                        }
                    }
                    else
                    {
                        if (wasMatch)
                        {
                            filtered.Remove(change.Previous.Value);
                        }
                    }
                    break;
                }

                case ListChangeReason.Refresh:
                {
                    var change   = item.Item;
                    var match    = change.Current.IsMatch;
                    var wasMatch = item.Item.Current.WasMatch;
                    if (match)
                    {
                        if (wasMatch)
                        {
                            //an update, so get the latest index and pass the index up the chain
                            var previous = filtered.Select(x => x.Item)
                                           .IndexOfOptional(change.Current.Item, ReferenceEqualityComparer <T> .Instance)
                                           .ValueOrThrow(() => new InvalidOperationException($"Cannot find index of {typeof(T).Name} -> {change.Previous.Value}. Expected to be in the list"));

                            filtered.RefreshAt(previous.Index);
                        }
                        else
                        {
                            filtered.Add(change.Current);
                        }
                    }
                    else
                    {
                        if (wasMatch)
                        {
                            filtered.Remove(change.Previous.Value);
                        }
                    }
                    break;
                }

                case ListChangeReason.Remove:
                {
                    var change = item.Item;
                    if (change.Current.IsMatch)
                    {
                        filtered.Remove(change.Current);
                    }
                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    filtered.RemoveMany(item.Range.Where(t => t.IsMatch));
                    break;
                }

                case ListChangeReason.Clear:
                {
                    filtered.ClearOrRemoveMany(item);
                    break;
                }
                }
            }
        }
示例#5
0
        private async Task Transform(ChangeAwareList <TransformedItemContainer> transformed, IChangeSet <TSource> changes)
        {
            if (changes is null)
            {
                throw new ArgumentNullException(nameof(changes));
            }

            foreach (var item in changes)
            {
                switch (item.Reason)
                {
                case ListChangeReason.Add:
                {
                    var change = item.Item;
                    if (change.CurrentIndex < 0 | change.CurrentIndex >= transformed.Count)
                    {
                        var container = await _containerFactory(item.Item.Current).ConfigureAwait(false);

                        transformed.Add(container);
                    }
                    else
                    {
                        var container = await _containerFactory(item.Item.Current).ConfigureAwait(false);

                        transformed.Insert(change.CurrentIndex, container);
                    }

                    break;
                }

                case ListChangeReason.AddRange:
                {
                    var tasks      = item.Range.Select(_containerFactory);
                    var containers = await Task.WhenAll(tasks).ConfigureAwait(false);

                    transformed.AddOrInsertRange(containers, item.Range.Index);
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var change    = item.Item;
                    var container = await _containerFactory(item.Item.Current).ConfigureAwait(false);

                    if (change.CurrentIndex == change.PreviousIndex)
                    {
                        transformed[change.CurrentIndex] = container;
                    }
                    else
                    {
                        transformed.RemoveAt(change.PreviousIndex);
                        transformed.Insert(change.CurrentIndex, container);
                    }

                    break;
                }

                case ListChangeReason.Remove:
                {
                    var  change   = item.Item;
                    bool hasIndex = change.CurrentIndex >= 0;

                    if (hasIndex)
                    {
                        transformed.RemoveAt(item.Item.CurrentIndex);
                    }
                    else
                    {
                        var toRemove = transformed.FirstOrDefault(t => ReferenceEquals(t.Source, t));

                        if (toRemove is not null)
                        {
                            transformed.Remove(toRemove);
                        }
                    }

                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    if (item.Range.Index >= 0)
                    {
                        transformed.RemoveRange(item.Range.Index, item.Range.Count);
                    }
                    else
                    {
                        var toRemove = transformed.Where(t => ReferenceEquals(t.Source, t)).ToArray();
                        transformed.RemoveMany(toRemove);
                    }

                    break;
                }

                case ListChangeReason.Clear:
                {
                    // i.e. need to store transformed reference so we can correctly clear
                    var toClear = new Change <TransformedItemContainer>(ListChangeReason.Clear, transformed);
                    transformed.ClearOrRemoveMany(toClear);

                    break;
                }

                case ListChangeReason.Moved:
                {
                    var  change   = item.Item;
                    bool hasIndex = change.CurrentIndex >= 0;
                    if (!hasIndex)
                    {
                        throw new UnspecifiedIndexException("Cannot move as an index was not specified");
                    }

                    if (transformed is IExtendedList <TransformedItemContainer> collection)
                    {
                        collection.Move(change.PreviousIndex, change.CurrentIndex);
                    }
                    else
                    {
                        var current = transformed[change.PreviousIndex];
                        transformed.RemoveAt(change.PreviousIndex);
                        transformed.Insert(change.CurrentIndex, current);
                    }

                    break;
                }
                }
            }
        }