コード例 #1
0
        public void ExtractSingleMemberSucceedsWhenOneMemberExistsTest()
        {
            Expression <Func <TestClass, int> > expr = p => p.Id;
            var memberExpression = MemberExtractor.ExtractSingleMember(expr);

            Assert.AreEqual(memberExpression.Member, typeof(TestClass).GetProperty(nameof(TestClass.Id)));
        }
コード例 #2
0
        public static IEnumerable <T> SetReferences <T, V, U>(
            this IEnumerable <T> source,
            Expression <Func <T, V> > property,
            IEnumerable <U> target,
            Expression <Func <T, U, bool> > joinExpression,
            KeyBuilder keyBuilder) where V : IEnumerable <U>
        {
            if (source == null || target == null)
            {
                return(source);
            }

            var member = MemberExtractor.ExtractSingleMember(property);
            var setter = typeof(T).CreateCollectionPropertySetter <T, U>(member.Member.Name, member.Type);

            var collection = source as ICollection <T> ?? source.ToList();

            //TODO see if this can be cached?
            Expression <Func <U, T, bool> > reverseJoin = Expression.Lambda <Func <U, T, bool> >(joinExpression.Body, joinExpression.Parameters[1], joinExpression.Parameters[0]);
            var targetLookup = target.ToExpressionKeyLookup(reverseJoin);

            var ifnullSetter = typeof(T).CreatePropertySetup <T, U>(member.Member.Name);

            if (targetLookup != null)
            {
                foreach (var parentEntity in collection)
                {
                    var existingChildEntities = ifnullSetter(parentEntity);

                    var childEntities = new HashSet <U>(
                        targetLookup.GetMatches(parentEntity),
                        keyBuilder.GetKeyComparer <U>());

                    childEntities.ExceptWith(existingChildEntities);
                    foreach (var childEntity in childEntities)
                    {
                        setter(parentEntity, childEntity);
                    }
                }

                return(collection);
            }

            var func = joinExpression.Compile();

            foreach (var childItem in collection)
            {
                ifnullSetter(childItem);

                foreach (var matchingParent in target.Where(x => func(childItem, x)))
                {
                    setter(childItem, matchingParent);
                }
            }


            return(collection);
        }
コード例 #3
0
        protected void AddRelationship <TEntity, TOther>(Expression <Func <TEntity, TOther> > memberExpr,
                                                         Expression <Func <TEntity, TOther, bool> > relationshipExpr)
        {
            var relationship = new Relationship(
                MemberExtractor.ExtractSingleMember(memberExpr).Member,
                memberExpr,
                relationshipExpr);

            var store = RelationshipsStore.AddOrUpdate(typeof(TEntity),
                                                       new TypeRelationships(typeof(TEntity), typeof(TEntity).GetRealBaseType(), relationship),
                                                       (_, tr) => new TypeRelationships(tr, relationship));

            UpdateTypeHierachies(store.BaseType, store.Type);
        }
コード例 #4
0
        public void ExtractSingleMemberFailWhenMulitpleMembersExistTest()
        {
            bool exceptionThrown = false;
            Expression <Func <TestClass, int> > expr = p => p.Id + p.ParentId.Value;

            try
            {
                MemberExtractor.ExtractSingleMember(expr);
            }
            catch (InvalidOperationException)
            {
                exceptionThrown = true;
            }

            Assert.IsTrue(exceptionThrown);
        }
コード例 #5
0
        public void ExtractSingleMemberFailWhenNoMembersExistTest()
        {
            bool exceptionThrown = false;
            Expression <Func <TestClass, int> > expr = p => 12;

            try
            {
                MemberExtractor.ExtractSingleMember(expr);
            }
            catch (ArgumentNullException)
            {
                exceptionThrown = true;
            }

            Assert.IsTrue(exceptionThrown);
        }
コード例 #6
0
        private static Func <T, int> CreateHashCode <T>(IEnumerable <LambdaExpression> keys)
        {
            var param          = Expression.Parameter(typeof(T), "source");
            var hasher         = Expression.New(typeof(HashCode));
            var hasherVariable = Expression.Variable(typeof(HashCode), "h");
            var assign         = Expression.Assign(hasherVariable, hasher);
            var expressions    = new List <Expression>
            {
                hasherVariable,
                assign
            };

            foreach (var key in keys)
            {
                var exprWithNewParam = ParameterReplacer.Replace(key, key.Parameters.First(), param) as LambdaExpression;
                var memberExpr       = MemberExtractor.ExtractSingleMember(exprWithNewParam.Body);
                var memberType       = memberExpr.Member.GetMemberUnderlyingType();

                var hashCodeAdd = Expression.Call(hasherVariable, nameof(HashCode.Add), new Type[] { key.ReturnType }, exprWithNewParam.Body);

                if (memberType.IsNullable())
                {
                    var isNull = Expression.NotEqual(memberExpr, Expression.Constant(null, memberType));
                    var @if    = Expression.IfThen(isNull, hashCodeAdd);
                    expressions.Add(@if);
                }
                else
                {
                    expressions.Add(hashCodeAdd);
                }
            }

            var returnTarget = Expression.Label(typeof(int));

            expressions.Add(Expression.Return(returnTarget,
                                              Expression.Call(hasherVariable, typeof(HashCode).GetMethod(nameof(HashCode.ToHashCode))), typeof(int)));
            expressions.Add(Expression.Label(returnTarget, Expression.Constant(default(int))));

            var block = Expression.Block(new[] { hasherVariable }, expressions);

            var lambda = Expression.Lambda <Func <T, int> >(block, param);

            return(lambda.Compile());
        }
コード例 #7
0
        public static IEnumerable <T> SetReferences <T, U>(
            this IEnumerable <T> source,
            Expression <Func <T, U> > property,
            IEnumerable <U> target,
            Expression <Func <T, U, bool> > joinExpression)
        {
            if (source == null || target == null)
            {
                return(source);
            }

            var member = MemberExtractor.ExtractSingleMember(property);
            var setter = property.Parameters[0].Type.CreatePropertySetter <T, U>(member.Member.Name);

            var collection = source as ICollection <T> ?? source.ToList();
            var lookup     = collection.ToExpressionKeyLookup(joinExpression);

            if (lookup != null)
            {
                foreach (var parentItem in target)
                {
                    foreach (var matchingChild in lookup.GetMatches(parentItem))
                    {
                        //set item to match.property
                        setter(matchingChild, parentItem);
                    }
                }
            }
            //fallback to looping through when no hashCode key can be created
            else
            {
                var func = joinExpression.Compile();
                foreach (var childItem in source)
                {
                    var matchingParent = target.FirstOrDefault(x => func(childItem, x));
                    setter(childItem, matchingParent);
                }
            }
            return(collection);
        }