public void Analyze_ExpressionHasMultipleParametersWithReduntantAccessors_ReturnsMinimalPropertyAccessTree()
        {
            Expression <Func <Person, SimpleNotifyValue, int> > ageAdder = (person, simpleNotify) => person.Age + person.Age + simpleNotify.Value + simpleNotify.Value;

            var tree = ExpressionPropertyAnalyzer.Analyze(ageAdder);

            Assert.AreEqual(2, tree.Children.Count);

            ParameterNode personParameterNode = (ParameterNode)tree.Children[0];

            Assert.AreEqual(1, personParameterNode.Children.Count);
            Assert.AreEqual("person", personParameterNode.Name);
            PropertyAccessNode personAgePropertyAccessNode = (PropertyAccessNode)personParameterNode.Children[0];

            Assert.AreEqual(typeof(Person), personAgePropertyAccessNode.Property.DeclaringType);
            Assert.AreEqual("Age", personAgePropertyAccessNode.PropertyName);

            ParameterNode simpleNotifyParameterNode = (ParameterNode)tree.Children[1];

            Assert.AreEqual(1, simpleNotifyParameterNode.Children.Count);
            Assert.AreEqual("simpleNotify", simpleNotifyParameterNode.Name);
            PropertyAccessNode simpleNotifyValuePropertyAccessNode = (PropertyAccessNode)simpleNotifyParameterNode.Children[0];

            Assert.AreEqual(typeof(SimpleNotifyValue), simpleNotifyValuePropertyAccessNode.Property.DeclaringType);
            Assert.AreEqual("Value", simpleNotifyValuePropertyAccessNode.PropertyName);
        }
Beispiel #2
0
        public DependsOnMethod <T> OnChanged <TResult>(Expression <Func <T, TResult> > propertyAccessor)
        {
            PropertyAccessTree propertyAccessTree = ExpressionPropertyAnalyzer.Analyze(propertyAccessor);

            if (propertyAccessTree.DoesEntireTreeSupportINotifyPropertyChanging)
            {
                if (_propertyChangeSubscribers == null)
                {
                    _propertyChangeSubscribers = new List <IPropertyAccessTreeSubscriber <DependsOnMethod <T> > >();
                }

                var subscriber = propertyAccessTree.CreateCallbackSubscription <DependsOnMethod <T> >(OnAnyPropertyInSubscriptionChanges);

                _propertyChangeSubscribers.Add(subscriber);
            }
            else
            {
                if (_accessTreesWithoutNotifyPropertyChanging == null)
                {
                    _accessTreesWithoutNotifyPropertyChanging = new List <PropertyAccessTree>();
                }
                _accessTreesWithoutNotifyPropertyChanging.Add(propertyAccessTree);
            }

            return(this);
        }
        public void Analyze_ExpressionContainsNewOperatorWithMemberAssignmentInitialization_ReturnsPropertyAccessTree()
        {
            Expression <Func <Person, Person> > expression = person => new Person()
            {
                Name = person.Name, Age = person.Age
            };

            var tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.IsInstanceOfType(typeof(ParameterNode), parameterNode);
            Assert.AreEqual(2, parameterNode.Children.Count);

            PropertyAccessNode ageNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_ageProperty, ageNode.Property);
            Assert.AreEqual(0, ageNode.Children.Count);

            PropertyAccessNode nameNode = (PropertyAccessNode)parameterNode.Children[1];

            Assert.AreEqual(_nameProperty, nameNode.Property);
            Assert.AreEqual(0, nameNode.Children.Count);
        }
        public void Analyze_ExpressionIncludesConstantImplementingINotifyPropertyChanged_TreeContainsTwoBranches()
        {
            Person localPersonAppearingAsConstantInExpression = new Person();
            Expression <Func <Person, int> > expression       = p => p.Age + localPersonAppearingAsConstantInExpression.Age;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(2, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.IsInstanceOfType(typeof(ParameterNode), parameterNode);
            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessNode parameterAgeNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_ageProperty, parameterAgeNode.Property);
            Assert.AreEqual(0, parameterAgeNode.Children.Count);

            PropertyAccessTreeNode constantNode = tree.Children[1];

            Assert.IsInstanceOfType(typeof(ConstantNode), constantNode);
            Assert.AreEqual(localPersonAppearingAsConstantInExpression, ((ConstantNode)constantNode).Value);
            Assert.AreEqual(1, constantNode.Children.Count);

            PropertyAccessNode constantAgeNode = (PropertyAccessNode)constantNode.Children[0];

            Assert.AreEqual(_ageProperty, constantAgeNode.Property);
            Assert.AreEqual(0, constantAgeNode.Children.Count);
        }
        public void Analyze_ConditionalExpressionBothOneLevelAndTwoLevelProperties_TreeCorrect()
        {
            Expression <Func <Person, int> > expression = p => p.Age > 3 ? p.Age : p.Brother.Age;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.AreEqual(2, parameterNode.Children.Count);

            PropertyAccessNode firstLevelAgeNode = (PropertyAccessNode)parameterNode.Children[1];

            Assert.AreEqual(_ageProperty, firstLevelAgeNode.Property);
            Assert.AreEqual(0, firstLevelAgeNode.Children.Count);

            PropertyAccessNode brotherNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_brotherProperty, brotherNode.Property);
            Assert.AreEqual(1, brotherNode.Children.Count);

            PropertyAccessNode secondLevelAgeNode = (PropertyAccessNode)brotherNode.Children[0];

            Assert.AreEqual(_ageProperty, secondLevelAgeNode.Property);
            Assert.AreEqual(0, secondLevelAgeNode.Children.Count);
        }
        public void Analyze_ExpressionContainsNothingWithINotifyPropertyChanged_ReturnsNull()
        {
            Expression <Func <int, bool> > expression = i => i == 0;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.IsNull(tree);
        }
        public void Analyze_SpecialTypeFilterWithExpressionThatFailsFilter_ReturnsPropertyAccessTree()
        {
            Expression <Func <string, bool> > expression = str => str.Length == 0;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression, type => type == typeof(int));

            Assert.IsNull(tree);
        }
        public void Analyze_ExpressionAccessesOnlyParameter_TreeHasOnlyParameter()
        {
            Expression <Func <Person, Person> > expression = p => p;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            Assert.IsInstanceOfType(typeof(ParameterNode), tree.Children[0]);
        }
Beispiel #9
0
        public void Analyze_ExpressionAccessesOnlyParameter_TreeHasOnlyParameter()
        {
            Expression <Func <Person, Person> > expression = p => p;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            tree.Children[0].Should().BeOfType <ParameterNode>();
        }
        public void Analyze_ExpressionContainsDelegate_ReturnsPropertyAccessTree()
        {
            Func <Person, string> del = person => person.Name;

            Expression <Func <Person, string> > expression = person => del(person);

            var tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.IsInstanceOfType(typeof(ParameterNode), parameterNode);
            Assert.AreEqual(0, parameterNode.Children.Count);
        }
        public void Analyze_ExpressionReturnsOneLevelProperty_TreeHasOneParameterBranchWithOneProperty()
        {
            Expression <Func <Person, int> > expression = p => p.Age;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessNode propertyNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_ageProperty, propertyNode.Property);
            Assert.AreEqual(0, propertyNode.Children.Count);
        }
        public void Analyze_ExpressionUsesMethodCallOnOneLevelProperty_TreeHasOneParameterBranchWithOneProperty()
        {
            Expression <Func <Person, bool> > expression = p => string.IsNullOrEmpty(p.Name);

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessNode propertyNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_nameProperty, propertyNode.Property);
            Assert.AreEqual(0, propertyNode.Children.Count);
        }
        public void Analyze_TwoLevelPropertyWhereSubPropertyIsNotINotifyPropertyChanged_TreeContainsFirstProperty()
        {
            Expression <Func <Person, bool> > expression = p => p.Name.Length == 0;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.IsInstanceOfType(typeof(ParameterNode), parameterNode);
            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessNode nameNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_nameProperty, nameNode.Property);
            Assert.AreEqual(0, nameNode.Children.Count);
        }
        public SortingReadOnlyContinuousCollection(IList <TSource> list,
                                                   Expression <Func <TSource, TKey> > keySelectorExpression,
                                                   bool descending)
            : base(list, ExpressionPropertyAnalyzer.Analyze(keySelectorExpression))
        {
            this.KeySelector = keySelectorExpression.CachedCompile();
            this.KeySorter   = new SortsSourceByKey <TSource, TKey>(this.KeySelector, descending);
            SetComparerChain(this.KeySorter);

            BuildItemsInSortOrder(this.Source);

            this.NotifyCollectionChangedMonitor.Add         += OnAdd;
            this.NotifyCollectionChangedMonitor.Remove      += OnRemove;
            this.NotifyCollectionChangedMonitor.Reset       += OnReset;
            this.NotifyCollectionChangedMonitor.Replace     += OnReplace;
            this.NotifyCollectionChangedMonitor.ItemChanged += OnItemChanged;
        }
        public void Analyze_SpecialTypeFilterWithExpressionThatPassesFilter_ReturnsPropertyAccessTree()
        {
            Expression <Func <string, bool> > expression = str => str.Length == 0;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression, type => type == typeof(string));

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.IsInstanceOfType(typeof(ParameterNode), parameterNode);
            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessNode lengthNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(typeof(string).GetProperty("Length"), lengthNode.Property);
            Assert.AreEqual(0, lengthNode.Children.Count);
        }
        public void Analyze_ExpressionContainsDelegateAndPropertyAccess_ReturnsPropertyAccessTree()
        {
            Expression <Func <Person, string> > expression = person => this.StringPassThrough(person.Name);

            var tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(2, tree.Children.Count);

            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.IsInstanceOfType(typeof(ParameterNode), parameterNode);
            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessTreeNode constantNode = tree.Children[1];

            Assert.IsInstanceOfType(typeof(ConstantNode), constantNode);
            Assert.AreEqual(1, constantNode.Children.Count);
        }
        public void Analyze_ExpressionContainsThis_TreeContainsOneBranch()
        {
            Expression <Func <Person, int> > expression = p => this.TestProperty;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(2, tree.Children.Count);

            PropertyAccessTreeNode constantNode = tree.Children[1];

            Assert.IsInstanceOfType(typeof(ConstantNode), constantNode);
            Assert.AreEqual(this, ((ConstantNode)constantNode).Value);
            Assert.AreEqual(1, constantNode.Children.Count);

            PropertyAccessNode testPropertyNode = (PropertyAccessNode)constantNode.Children[0];

            Assert.AreEqual(GetType().GetProperty("TestProperty"), testPropertyNode.Property);
            Assert.AreEqual(0, testPropertyNode.Children.Count);
        }
        public SelectManyReadOnlyContinuousCollection(
            IList <TSource> list,
            Expression <Func <TSource, IList <TResult> > > manySelector) :
            base(list, ExpressionPropertyAnalyzer.Analyze(manySelector))
        {
            _sourceToCollectionNode = new Dictionary <TSource, List <IndexingSkipList <IList <TResult> > .Node> >();
            _collectionToNode       = new Dictionary <IList <TResult>, List <IndexingSkipList <IList <TResult> > .Node> >();
            _weakEventHandlers      = new Dictionary <IList <TResult>, WeakEventHandler>();
            _collectionIndex        = new IndexingSkipList <IList <TResult> >();

            _selectorFunction = manySelector.CachedCompile();
            RecordCurrentValues(_collectionIndex.TopLeft, this.Source);

            this.NotifyCollectionChangedMonitor.Add         += OnAdd;
            this.NotifyCollectionChangedMonitor.Remove      += OnRemove;
            this.NotifyCollectionChangedMonitor.Reset       += OnReset;
            this.NotifyCollectionChangedMonitor.Move        += OnMove;
            this.NotifyCollectionChangedMonitor.Replace     += OnReplace;
            this.NotifyCollectionChangedMonitor.ItemChanged += OnItemChanged;
        }
        internal GroupingReadOnlyContinuousCollection(
            IList <TSource> list,
            Expression <Func <TSource, TKey> > keySelectorExpression)
            : base(list, ExpressionPropertyAnalyzer.Analyze(keySelectorExpression))
        {
            this.KeySelector = keySelectorExpression.CachedCompile();
            this.Output      = new ContinuousCollection <GroupedReadOnlyContinuousCollection <TKey, TSource> >();

            this.ItemToGroupIndex = new Dictionary <TSource, GroupedReadOnlyContinuousCollection <TKey, TSource> >();

            AddNewItems(this.Source);

            this.NotifyCollectionChangedMonitor.Add         += OnAdd;
            this.NotifyCollectionChangedMonitor.Remove      += OnRemove;
            this.NotifyCollectionChangedMonitor.Reset       += OnReset;
            this.NotifyCollectionChangedMonitor.Replace     += OnReplace;
            this.NotifyCollectionChangedMonitor.ItemChanged += OnItemChanged;

            this.Output.CollectionChanged += OnOutputCollectionChanged;
        }
        public FilteringReadOnlyContinuousCollection(IList <TSource> list, Expression <Func <TSource, bool> > expression)
            : base(list, ExpressionPropertyAnalyzer.Analyze(expression))
        {
#if DEBUG
            this.Expr = expression;
#endif
            this.FilterFunction = expression.CachedCompile();

            this.Output     = new ContinuousCollection <TSource>();
            this.ItemLookup = new HashSet <TSource>();

            this.Output.CollectionChanged += RefireCollectionChangedFromOutput;

            AddNewItems(this.Source);

            this.NotifyCollectionChangedMonitor.Add         += OnAdd;
            this.NotifyCollectionChangedMonitor.Remove      += OnRemove;
            this.NotifyCollectionChangedMonitor.Reset       += OnReset;
            this.NotifyCollectionChangedMonitor.Replace     += OnReplace;
            this.NotifyCollectionChangedMonitor.ItemChanged += OnItemChanged;
        }
        public void Analyze_ExpressionReturnsTwoLevelProperty_TreeHasOneParameterBranchWithTwoProperties()
        {
            Expression <Func <Person, int> > expression = p => p.Brother.Age;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.AreEqual(1, parameterNode.Children.Count);

            PropertyAccessNode brotherNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_brotherProperty, brotherNode.Property);
            Assert.AreEqual(1, brotherNode.Children.Count);

            PropertyAccessNode ageNode = (PropertyAccessNode)brotherNode.Children[0];

            Assert.AreEqual(_ageProperty, ageNode.Property);
            Assert.AreEqual(0, ageNode.Children.Count);
        }
        public void Analyze_ConditionalExpressionReferencingTwoProperties_TreeContainsOnePropertyBranchWithBothProperties()
        {
            Expression <Func <Person, int> > expression = p => string.IsNullOrEmpty(p.Name) ? p.Age : 0;

            PropertyAccessTree tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            Assert.AreEqual(2, parameterNode.Children.Count);

            PropertyAccessNode ageNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_ageProperty, ageNode.Property);
            Assert.AreEqual(0, ageNode.Children.Count);

            PropertyAccessNode nameNode = (PropertyAccessNode)parameterNode.Children[1];

            Assert.AreEqual(_nameProperty, nameNode.Property);
            Assert.AreEqual(0, nameNode.Children.Count);
        }
Beispiel #23
0
        public void Analyze_ExpressionContainsNewOperatorWithConstructorArguments_ReturnsPropertyAccessTree()
        {
            Expression <Func <Person, Person> > expression = person => new Person(person.Name, person.Age);

            var tree = ExpressionPropertyAnalyzer.Analyze(expression);

            Assert.AreEqual(1, tree.Children.Count);
            PropertyAccessTreeNode parameterNode = tree.Children[0];

            parameterNode.Should().BeOfType <ParameterNode>();
            Assert.AreEqual(2, parameterNode.Children.Count);

            PropertyAccessNode ageNode = (PropertyAccessNode)parameterNode.Children[0];

            Assert.AreEqual(_ageProperty, ageNode.Property);
            Assert.AreEqual(0, ageNode.Children.Count);

            PropertyAccessNode nameNode = (PropertyAccessNode)parameterNode.Children[1];

            Assert.AreEqual(_nameProperty, nameNode.Property);
            Assert.AreEqual(0, nameNode.Children.Count);
        }
Beispiel #24
0
        protected void Register <TResult>(Expression <Func <T, TResult> > propertyAccessor, FireOn fireOn)
        {
            PropertyAccessTree propertyAccessTree = ExpressionPropertyAnalyzer.Analyze(propertyAccessor);

            if (propertyAccessTree.DoesEntireTreeSupportINotifyPropertyChanging)
            {
                if (_propertyChangeSubscribers == null)
                {
                    _propertyChangeSubscribers = new List <IPropertyAccessTreeSubscriber <ReactiveMethod <T> > >();
                }

                Action <ReactiveMethod <T>, object, PropertyChangingEventArgs> onPropertyChanging = OnAnyPropertyInSubscriptionChanging;
                Action <ReactiveMethod <T>, object, PropertyChangedEventArgs>  onPropertyChanged  = OnAnyPropertyInSubscriptionChanged;

                if ((fireOn & FireOn.PropertyChanging) != FireOn.PropertyChanging)
                {
                    onPropertyChanging = null;
                }

                if ((fireOn & FireOn.PropertyChanged) != FireOn.PropertyChanged)
                {
                    onPropertyChanged = null;
                }

                var subscriber = propertyAccessTree.CreateCallbackSubscription <ReactiveMethod <T> >(
                    onPropertyChanging, onPropertyChanged
                    );

                _propertyChangeSubscribers.Add(subscriber);
            }
            else if ((fireOn & FireOn.PropertyChanged) == FireOn.PropertyChanged)
            {
                if (_accessTreesWithoutNotifyPropertyChanging == null)
                {
                    _accessTreesWithoutNotifyPropertyChanging = new List <PropertyAccessTree>();
                }
                _accessTreesWithoutNotifyPropertyChanging.Add(propertyAccessTree);
            }
        }
        public GroupJoinReadOnlyContinuousCollection(
            IList <TOuter> outer,
            IList <TInner> inner,
            Expression <Func <TOuter, TKey> > outerKeySelector,
            Expression <Func <TInner, TKey> > innerKeySelector,
            Expression <Func <TOuter, ReadOnlyContinuousCollection <TInner>, TResult> > resultSelector)
        {
            _outer = outer;
            _inner = inner;

            _outerKeySelector = outerKeySelector.CachedCompile();
            _innerKeySelector = innerKeySelector.CachedCompile();
            _resultSelector   = resultSelector.CachedCompile();

            _keyToOuterLookup = new Dictionary <TKey, List <OuterEntry> >(_outer.Count);
            _outerEntries     = new Dictionary <TOuter, OuterEntry>(_outer.Count);

            _keyToInnerLookup = new Dictionary <TKey, List <TInner> >(_inner.Count);
            _innerEntries     = new Dictionary <TInner, InnerEntry>();

            _outerReferenceTracker = new ReferenceCountTracker <TOuter>(outer);

            RebuildAll();

            _outerNotifyCollectionChangedMonitor              = new NotifyCollectionChangedMonitor <TOuter>(ExpressionPropertyAnalyzer.Analyze(outerKeySelector), outer);
            _outerNotifyCollectionChangedMonitor.Add         += OnOuterAdd;
            _outerNotifyCollectionChangedMonitor.Remove      += OnOuterRemove;
            _outerNotifyCollectionChangedMonitor.Reset       += OnOuterReset;
            _outerNotifyCollectionChangedMonitor.Move        += OnOuterMove;
            _outerNotifyCollectionChangedMonitor.Replace     += OnOuterItemReplace;
            _outerNotifyCollectionChangedMonitor.ItemChanged += OnOuterKeyChanged;

            _innerNotifyCollectionChangedMonitor              = new NotifyCollectionChangedMonitor <TInner>(ExpressionPropertyAnalyzer.Analyze(innerKeySelector), inner);
            _innerNotifyCollectionChangedMonitor.Add         += OnInnerAdd;
            _innerNotifyCollectionChangedMonitor.Remove      += OnInnerRemove;
            _innerNotifyCollectionChangedMonitor.Reset       += OnInnerReset;
            _innerNotifyCollectionChangedMonitor.Move        += OnInnerMove;
            _innerNotifyCollectionChangedMonitor.Replace     += OnInnerItemReplace;
            _innerNotifyCollectionChangedMonitor.ItemChanged += OnInnerItemChanged;
        }