internal static Position processAddSourceItem(int newSourceIndex, bool predicateValue, ref Position newItemPosition, ref int?newFilteredIndex, List <FilteringItemInfo> filteringItemInfos, Positions <Position> filteredPositions, int count) { Position nextItemPosition; if (newSourceIndex < filteringItemInfos.Count) { FilteringItemInfo oldItemInfo = filteringItemInfos[newSourceIndex]; Position oldItemInfoNextFilteredItemPosition = oldItemInfo.NextFilteredItemPosition; Position oldItemInfoFilteredPosition = oldItemInfo.FilteredPosition; if (predicateValue) { if (oldItemInfoFilteredPosition == null) { newItemPosition = filteredPositions.Insert(oldItemInfoNextFilteredItemPosition.Index); nextItemPosition = oldItemInfoNextFilteredItemPosition; newFilteredIndex = newItemPosition.Index; } else { int filteredIndex = oldItemInfoFilteredPosition.Index; newFilteredIndex = filteredIndex; newItemPosition = filteredPositions.Insert(filteredIndex); nextItemPosition = oldItemInfoFilteredPosition; } modifyNextFilteredItemIndex(newSourceIndex, newItemPosition, filteringItemInfos); } else { nextItemPosition = oldItemInfoFilteredPosition ?? oldItemInfoNextFilteredItemPosition; } } else { if (predicateValue) { newItemPosition = filteredPositions.List[count]; newFilteredIndex = count; nextItemPosition = filteredPositions.Add(); } else { //здесь newPositionIndex = null; так и должно быть nextItemPosition = filteredPositions.List[count]; } } return(nextItemPosition); }
//TODO Uncomment new feature and write test //[ObservableComputationsCall] //public Filtering<TSourceItem> TryConstructInsertOrRemoveRequestHandlers() //{ // ConstructInsertOrRemoveActionsVisitor // constructInsertOrRemoveActionsVisitor = // new ConstructInsertOrRemoveActionsVisitor(); // constructInsertOrRemoveActionsVisitor.Visit(_predicateExpressionOriginal); // Action<TSourceItem> transformSourceItemIntoMember = // constructInsertOrRemoveActionsVisitor.TransformSourceItemIntoMember; // if (transformSourceItemIntoMember != null) // { // InsertItemRequestHandler = (index, item) => transformSourceItemIntoMember(item); // } // Action<TSourceItem> transformSourceItemNotIntoMember = // constructInsertOrRemoveActionsVisitor.TransformSourceItemIntoNotMember; // if (transformSourceItemNotIntoMember != null) // { // RemoveItemRequestHandler = index => transformSourceItemNotIntoMember(this[index]); // } // return this; //} //private class ConstructInsertOrRemoveActionsVisitor : ExpressionVisitor //{ // public Action<TSourceItem> TransformSourceItemIntoMember; // public Action<TSourceItem> TransformSourceItemIntoNotMember; // #region Overrides of ExpressionVisitor // //TODO !sourceItem.NullableProp.HasValue должно преобразооваться в sourceItem.NullableProp == null // // TODO обрабытывать выражения типа '25 == sourceItem.Id' // protected override Expression VisitBinary(BinaryExpression node) // { // ExpressionType nodeType = node.NodeType; // if (nodeType == ExpressionType.Equal || nodeType == ExpressionType.NotEqual) // { // if (node.Left is MemberExpression memberExpression) // { // Expression rightExpression = node.Right; // // ReSharper disable once PossibleNullReferenceException // MemberInfo memberExpressionMember = memberExpression.Member; // Type declaringType = memberExpressionMember.DeclaringType; // // ReSharper disable once PossibleNullReferenceException // if (declaringType.IsConstructedGenericType // && declaringType.GetGenericTypeDefinition() == typeof(Nullable<>) // && memberExpressionMember.Name == "Value") // { // memberExpression = (MemberExpression) memberExpression.Expression; // rightExpression = Expression.Convert(rightExpression, // typeof (Nullable<>).MakeGenericType(node.Left.Type)); // } // ParameterExpression parameterExpression = getParameterExpression(memberExpression); // if (parameterExpression != null) // { // if (memberExpression.Type != rightExpression.Type) // { // rightExpression = Expression.Convert(rightExpression, memberExpression.Type); // } // if (!memberExpressionMember.IsReadOnly()) // { // if (nodeType == ExpressionType.Equal) // { // TransformSourceItemIntoMember = Expression.Lambda<Action<TSourceItem>>(Expression.Assign(memberExpression, rightExpression), parameterExpression).Compile(); // } // else if (nodeType == ExpressionType.NotEqual) // { // TransformSourceItemIntoNotMember = Expression.Lambda<Action<TSourceItem>>(Expression.Assign(memberExpression, rightExpression), parameterExpression).Compile(); // } // } // } // } // } // return node; // } // private ParameterExpression getParameterExpression(MemberExpression memberExpression) // { // if (memberExpression.Expression is ParameterExpression parameterExpression) // { // return parameterExpression; // } // if (memberExpression.Expression is MemberExpression expressionMemberExpression) // { // return getParameterExpression(expressionMemberExpression); // memberExpression.Expression может быть не MemberExpression // } // return null; // } // #endregion //} protected override void processSource() { int originalCount = _items.Count; if (_sourceReadAndSubscribed) { Utils.disposeExpressionItemInfos(_itemInfos, _predicateExpressionCallCount, this); Utils.removeDownstreamConsumedComputing(_itemInfos, this); _filteredPositions = new Positions <Position>(new List <Position>(_initialCapacity)); Utils.disposeSource( _sourceScalar, _source, out _itemInfos, out _sourcePositions, _sourceAsList, handleSourceCollectionChanged); _sourceReadAndSubscribed = false; } Utils.changeSource(ref _source, _sourceScalar, _downstreamConsumedComputings, _consumers, this, out _sourceAsList, false); if (_source != null && _isActive) { Utils.initializeFromObservableCollectionWithChangeMarker( _source, ref _sourceAsList, ref _rootSourceWrapper, ref _lastProcessedSourceChangeMarker); Position nextItemPosition = _filteredPositions.Add(); int count = _sourceAsList.Count; TSourceItem[] sourceCopy = new TSourceItem[count]; _sourceAsList.CopyTo(sourceCopy, 0); _sourceAsList.CollectionChanged += handleSourceCollectionChanged; int insertingIndex = 0; int sourceIndex; for (sourceIndex = 0; sourceIndex < count; sourceIndex++) { TSourceItem sourceItem = sourceCopy[sourceIndex]; Position currentFilteredItemPosition = null; FilteringItemInfo itemInfo = registerSourceItem(sourceItem, sourceIndex, null, null); if (_thisAsFiltering.applyPredicate(sourceItem, itemInfo.PredicateFunc)) { if (originalCount > insertingIndex) { _items[insertingIndex++] = sourceItem; } else { _items.Insert(insertingIndex++, sourceItem); } currentFilteredItemPosition = nextItemPosition; nextItemPosition = _filteredPositions.Add(); } itemInfo.FilteredPosition = currentFilteredItemPosition; itemInfo.NextFilteredItemPosition = nextItemPosition; } for (int index = originalCount - 1; index >= insertingIndex; index--) { _items.RemoveAt(index); } _sourceReadAndSubscribed = true; } else { _items.Clear(); } reset(); }
private void initializeFromSource() { int originalCount = _items.Count; if (_sourceNotifyCollectionChangedEventHandler != null) { int itemInfosCount = _itemInfos.Count; for (int index = 0; index < itemInfosCount; index++) { ItemInfo itemInfo = _itemInfos[index]; ExpressionWatcher expressionWatcher = itemInfo.ExpressionWatcher; expressionWatcher.Dispose(); } int capacity = _sourceScalar != null?Utils.getCapacity(_sourceScalar) : Utils.getCapacity(_source); _filteredPositions = new Positions <Position>(new List <Position>(_initialCapacity)); _itemInfos = new List <ItemInfo>(capacity); _sourcePositions = new Positions <ItemInfo>(_itemInfos); if (_rootSourceWrapper) { _sourceAsList.CollectionChanged -= _sourceNotifyCollectionChangedEventHandler; } else { _sourceAsList.CollectionChanged -= _sourceWeakNotifyCollectionChangedEventHandler.Handle; _sourceWeakNotifyCollectionChangedEventHandler = null; } _sourceNotifyCollectionChangedEventHandler = null; } if (_sourceScalar != null) { _source = _sourceScalar.Value; } _sourceAsList = null; if (_source != null) { if (_source is ObservableCollectionWithChangeMarker <TSourceItem> sourceAsList) { _sourceAsList = sourceAsList; _rootSourceWrapper = false; } else { _sourceAsList = new RootSourceWrapper <TSourceItem>(_source); _rootSourceWrapper = true; } _lastProcessedSourceChangeMarker = _sourceAsList.ChangeMarkerField; Position nextItemPosition = _filteredPositions.Add(); int count = _sourceAsList.Count; int insertingIndex = 0; int sourceIndex; for (sourceIndex = 0; sourceIndex < count; sourceIndex++) { TSourceItem sourceItem = _sourceAsList[sourceIndex]; Position currentFilteredItemPosition = null; ItemInfo itemInfo = registerSourceItem(sourceItem, sourceIndex, null, null); if (ApplyPredicate(sourceIndex)) { if (originalCount > insertingIndex) { _items[insertingIndex++] = sourceItem; } else { _items.Insert(insertingIndex++, sourceItem); } currentFilteredItemPosition = nextItemPosition; nextItemPosition = _filteredPositions.Add(); } itemInfo.FilteredPosition = currentFilteredItemPosition; itemInfo.NextFilteredItemPosition = nextItemPosition; } for (int index = originalCount - 1; index >= insertingIndex; index--) { _items.RemoveAt(index); } _sourceNotifyCollectionChangedEventHandler = handleSourceCollectionChanged; if (_rootSourceWrapper) { _sourceAsList.CollectionChanged += _sourceNotifyCollectionChangedEventHandler; } else { _sourceWeakNotifyCollectionChangedEventHandler = new WeakNotifyCollectionChangedEventHandler(_sourceNotifyCollectionChangedEventHandler); _sourceAsList.CollectionChanged += _sourceWeakNotifyCollectionChangedEventHandler.Handle; } } else { _items.Clear(); } reset(); }