public NotifyCollectionChangedMonitor(PropertyAccessTree propertyAccessTree, IList <T> input) { if (input == null) { throw new ArgumentNullException("input"); } INotifyCollectionChanged inputAsINotifyCollectionChanged = input as INotifyCollectionChanged; if (inputAsINotifyCollectionChanged == null) { throw new ArgumentException("Collections must implement INotifyCollectionChanged to work with CLINQ"); } _input = input; this.PropertyAccessTree = propertyAccessTree; this.ReferenceCountTracker = new ReferenceCountTracker <T>(); SetupPropertyChangeSubscription(); SubscribeToItems(_input); WeakNotifyCollectionChangedEventHandler.Register( inputAsINotifyCollectionChanged, this, (me, sender, args) => me.OnCollectionChanged(sender, args)); }
public PropertyNotifier(PropertyAccessTree tree) : base() { if (tree == null) { throw new ArgumentNullException("tree"); } PropertyAccessTree = tree; EntireTreeSupportINotifyPropertyChanging = PropertyAccessTree.DoesEntireTreeSupportINotifyPropertyChanging; }
public static PropertyAccessTree Analyze <T, TResult>(Expression <Func <T, TResult> > expression, Predicate <Type> typeFilter) { if (!typeFilter(typeof(T))) { return(null); } PropertyAccessTree tree = AnalyzeLambda(expression, typeFilter); return(tree); }
public PropertyAccessTreeSubscriberINotifyPropertyChanging( PropertyAccessTree propertyAccessTree, Action <TListener, object> subscriberCallback) { _subscriptions = new List <RootSubscription>(); _propertyAccessTree = propertyAccessTree; for (int i = 0; i < propertyAccessTree.Children.Count; i++) { var rootSubscription = new RootSubscription(subscriberCallback, propertyAccessTree.Children[i]); _subscriptions.Add(rootSubscription); } }
private static PropertyAccessTree AnalyzeLambda(LambdaExpression expression, Predicate <Type> typeFilter) { PropertyAccessTree tree = new PropertyAccessTree(); //This is done to ensure that the tree has all the parameters and in the same order. for (int i = 0; i < expression.Parameters.Count; i++) { ParameterExpression parameterExpression = expression.Parameters[0]; tree.Children.Add(new ParameterNode(parameterExpression.Type, parameterExpression.Name)); } BuildUnoptimizedTree(tree, expression.Body, typeFilter); RemoveRedundantNodesFromTree(tree.Children); ApplyTypeFilter(tree.Children, typeFilter); return(tree); }
private static void AddBranch(PropertyAccessTree tree, Stack <PropertyAccessTreeNode> currentNodeBranch) { if (currentNodeBranch.Count == 0) { return; } PropertyAccessTreeNode currentNode = currentNodeBranch.Pop(); tree.Children.Add(currentNode); while (currentNodeBranch.Count != 0) { PropertyAccessTreeNode nextNode = currentNodeBranch.Pop(); currentNode.Children.Add(nextNode); currentNode = nextNode; } }
internal void SubscribeToChanges(T subject) { if (EntireTreeSupportINotifyPropertyChanging) { if (_PropertyAccessTree == null) { _PropertyAccessTree = PropertyAccessTree.CreateCallbackSubscription <PropertyNotifier <T> >(OnItemChanging, OnItemChanged); } _PropertyAccessTree.SubscribeToChanges(subject, this); } else { if (_Subscriptions == null) { _Subscriptions = new Dictionary <T, SubscriptionTree>(); } SubscriptionTree tree = PropertyAccessTree.CreateSubscriptionTree(subject); tree.PropertyChanged += OnAnyPropertyChangeInSubscriptionTree; _Subscriptions.Add(subject, tree); } }
internal ReadOnlyAdapterContinuousCollection(IList <TSource> list, PropertyAccessTree propertyAccessTree) { this.Source = list; this.NotifyCollectionChangedMonitor = new NotifyCollectionChangedMonitor <TSource>(propertyAccessTree, list); }
private static void BuildBranches(Expression expression, PropertyAccessTree tree, Stack <PropertyAccessTreeNode> currentNodeBranch, Predicate <Type> typeFilter) { BinaryExpression binaryExpression = expression as BinaryExpression; if (binaryExpression != null) { BuildBranches(binaryExpression.Left, tree, currentNodeBranch, typeFilter); BuildBranches(binaryExpression.Right, tree, currentNodeBranch, typeFilter); return; } UnaryExpression unaryExpression = expression as UnaryExpression; if (unaryExpression != null) { BuildBranches(unaryExpression.Operand, tree, currentNodeBranch, typeFilter); return; } MethodCallExpression methodCallExpression = expression as MethodCallExpression; if (methodCallExpression != null) { foreach (Expression argument in methodCallExpression.Arguments) { BuildBranches(argument, tree, currentNodeBranch, typeFilter); } return; } ConditionalExpression conditionalExpression = expression as ConditionalExpression; if (conditionalExpression != null) { BuildBranches(conditionalExpression.Test, tree, currentNodeBranch, typeFilter); BuildBranches(conditionalExpression.IfTrue, tree, currentNodeBranch, typeFilter); BuildBranches(conditionalExpression.IfFalse, tree, currentNodeBranch, typeFilter); return; } InvocationExpression invocationExpression = expression as InvocationExpression; if (invocationExpression != null) { foreach (Expression argument in invocationExpression.Arguments) { BuildBranches(argument, tree, currentNodeBranch, typeFilter); } BuildBranches(invocationExpression.Expression, tree, currentNodeBranch, typeFilter); return; } switch (expression.NodeType) { case ExpressionType.MemberAccess: MemberExpression memberExpression = (MemberExpression)expression; PropertyInfo property = memberExpression.Member as PropertyInfo; FieldInfo fieldInfo = memberExpression.Member as FieldInfo; if (property != null) { PropertyAccessNode node = new PropertyAccessNode(property); currentNodeBranch.Push(node); BuildBranches(memberExpression.Expression, tree, currentNodeBranch, typeFilter); } else if (fieldInfo != null) { if (typeFilter(fieldInfo.FieldType)) { ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression; if (constantExpression.Value != null) { object value = fieldInfo.GetValue(constantExpression.Value); ConstantNode constantNode = new ConstantNode((INotifyPropertyChanged)value); currentNodeBranch.Push(constantNode); AddBranch(tree, currentNodeBranch); } } else { currentNodeBranch.Clear(); } } else { BuildBranches(memberExpression.Expression, tree, currentNodeBranch, typeFilter); } break; case ExpressionType.Parameter: ParameterExpression parameterExpression = (ParameterExpression)expression; ParameterNode parameterNode = new ParameterNode(expression.Type, parameterExpression.Name); currentNodeBranch.Push(parameterNode); AddBranch(tree, currentNodeBranch); break; case ExpressionType.Constant: { ConstantExpression constantExpression = (ConstantExpression)expression; if (typeFilter(constantExpression.Type) && constantExpression.Value != null) { ConstantNode constantNode = new ConstantNode((INotifyPropertyChanged)constantExpression.Value); currentNodeBranch.Push(constantNode); AddBranch(tree, currentNodeBranch); } else { currentNodeBranch.Clear(); } } break; case ExpressionType.New: { NewExpression newExpression = (NewExpression)expression; foreach (Expression argument in newExpression.Arguments) { BuildBranches(argument, tree, currentNodeBranch, typeFilter); } } break; case ExpressionType.MemberInit: { MemberInitExpression memberInitExpression = (MemberInitExpression)expression; BuildBranches(memberInitExpression.NewExpression, tree, currentNodeBranch, typeFilter); foreach (var memberBinding in memberInitExpression.Bindings) { MemberAssignment assignment = memberBinding as MemberAssignment; if (assignment != null) { BuildBranches(assignment.Expression, tree, currentNodeBranch, typeFilter); } } } break; default: throw new InvalidProgramException(string.Format("CLINQ does not support expressions of type: {0}", expression.NodeType)); } }
private static void BuildUnoptimizedTree(PropertyAccessTree tree, Expression expression, Predicate <Type> typeFilter) { var currentNodeBranch = new Stack <PropertyAccessTreeNode>(); BuildBranches(expression, tree, currentNodeBranch, typeFilter); }
public static PropertyAccessTree Analyze <T0, T1, TResult>(Expression <Func <T0, T1, TResult> > expression) { PropertyAccessTree tree = AnalyzeLambda(expression, DoesTypeImplementINotifyPropertyChanged); return(tree); }