internal static bool ProcessChangeSourceItem <TSourceItem>(int sourceIndex, TSourceItem sourceItem, List <FilteringItemInfo> filteringItemInfos, IFiltering <TSourceItem> filtering, Positions <Position> filteredPositions, CollectionComputing <TSourceItem> current, ExpressionWatcher expressionWatcher) { if (expressionWatcher._disposed) { return(false); } FilteringItemInfo itemInfo = filteringItemInfos[sourceIndex]; bool newPredicateValue = filtering.applyPredicate(sourceItem, itemInfo.PredicateFunc); bool oldPredicateValue = itemInfo.FilteredPosition != null; if (newPredicateValue != oldPredicateValue) { if (newPredicateValue) { int newIndex = itemInfo.NextFilteredItemPosition.Index; itemInfo.FilteredPosition = filteredPositions.Insert(newIndex); newIndex = itemInfo.FilteredPosition.Index; modifyNextFilteredItemIndex(sourceIndex, itemInfo.FilteredPosition, filteringItemInfos); current.baseInsertItem(newIndex, sourceItem); return(true); } else // if (oldPredicaeValue) { int index = itemInfo.FilteredPosition.Index; filteredPositions.Remove(index); itemInfo.FilteredPosition = null; modifyNextFilteredItemIndex(sourceIndex, itemInfo.NextFilteredItemPosition, filteringItemInfos); current.baseRemoveItem(index); return(true); } } return(false); }
//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(); }