Beispiel #1
0
        private static Expression BuildRelationUpdateBlock(
            EntityFieldInfo fromKey, PropertyInfo fromProperty, EntityInfo toEntity, PropertyInfo toProperty, Expression varFromEntity, Expression varDict)
        {
            var actions = new List <Expression>();

            /**
             * var posts = dict[blog.BlogId];
             * blog.Posts.AddRange(posts);
             */
            var toEnumType = typeof(IEnumerable <>).MakeGenericType(toEntity.Type);
            var fkExpr     = Expression.Property(varFromEntity, fromKey.ClrProperty);

            // var posts = dicts[blog.BlogId];
            var varTs = Expression.Variable(toEnumType, "rts");

            var keyType      = varDict.Type.GenericTypeArguments.First();
            var castExpr     = Expression.Convert(fkExpr, keyType);
            var dictItemExpr = Expression.Property(varDict, "Item", castExpr);

            var varTsAssignExpr = Expression.Assign(varTs, dictItemExpr);

            actions.Add(varTsAssignExpr);

            if (fromProperty != null)
            {
                // blog.Posts.AddRange(posts);
                var fmExpr      = Expression.Property(varFromEntity, fromProperty);
                var constructor = fmExpr.Type.GetConstructor(new[] { varTs.Type });
                var cExpr       = Expression.New(constructor, varTs);
                var arcExpr     = Expression.Assign(fmExpr, cExpr);

                actions.Add(arcExpr);
            }

            /**
             * foreach (var post in posts)
             *     post.Blog = blog;
             */
            if (toProperty != null)
            {
                var varToEntity   = Expression.Parameter(toEntity.Type, "t");
                var tfmExpr       = Expression.Property(varToEntity, toProperty);
                var tfmAssignExpr = Expression.Assign(tfmExpr, varFromEntity);
                var tkLoop        = MakeForEach(varTs, varToEntity, tfmAssignExpr);

                actions.Add(tkLoop);
            }

            var updateBlockExpr = Expression.Block(new[] { varTs }, actions.ToArray());

            // ContainsKey(TKey key)
            var ccExpr = Expression.Call(varDict, "ContainsKey", null, castExpr);
            var ifExpr = Expression.IfThen(ccExpr, updateBlockExpr);

            return(ifExpr);
        }
Beispiel #2
0
        private static MethodCallExpression GetToDictCall(EntityInfo toEntity, EntityFieldInfo toKey, Expression toParam)
        {
            //  GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
            var gParam  = Expression.Parameter(toEntity.Type, "t");
            var gBody   = Expression.Property(gParam, toKey.ClrProperty);
            var gLambda = Expression.Lambda(gBody, gParam);
            var gCall   = Expression.Call(typeof(Enumerable), nameof(Enumerable.GroupBy), new[] { gParam.Type, gBody.Type }, toParam, gLambda);

            // ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
            var tdParam  = Expression.Parameter(typeof(IGrouping <,>).MakeGenericType(toKey.ValType, toEntity.Type));
            var tdBody   = Expression.Property(tdParam, "Key");
            var tdLambda = Expression.Lambda(tdBody, tdParam);
            var tdCall   = Expression.Call(typeof(Enumerable), nameof(Enumerable.ToDictionary), new[] { tdParam.Type, tdBody.Type }, gCall, tdLambda);

            return(tdCall);
        }
Beispiel #3
0
        private static LambdaExpression MakeFillerFunc(
            Expression memberExpr, Type fromEnumType, Type toEnumType, EntityInfo fromEntity, EntityInfo toEntity,
            EntityFieldInfo fromKey, EntityFieldInfo toKey, PropertyInfo fromProp, PropertyInfo toProp)
        {
            var fromParam = Expression.Parameter(typeof(List <object>), "fs");
            var toParam   = Expression.Parameter(typeof(List <object>), "ts");

            var varFromArr = Expression.Variable(fromEnumType, "fromArr");
            var varToArr   = Expression.Variable(toEnumType, "toArr");

            var fromCastCall = Expression.Call(typeof(Enumerable), nameof(Enumerable.Cast), new[] { fromEntity.Type }, fromParam);
            var toCastCall   = Expression.Call(typeof(Enumerable), nameof(Enumerable.Cast), new[] { toEntity.Type }, toParam);

            var varFromArrAssign = Expression.Assign(varFromArr, fromCastCall);
            var varToArrAssign   = Expression.Assign(varToArr, toCastCall);

            // create dictionary for toEntities
            // var dicts = ps.GroupBy(p => p.BlogId).ToDictionary(bid => bid.Key);
            var tdCall            = GetToDictCall(toEntity, toKey, varToArr);
            var varDict           = Expression.Variable(tdCall.Type, "toDict");
            var varDictAssignExpr = Expression.Assign(varDict, tdCall);

            var varFromEntity = Expression.Parameter(fromEntity.Type, "f");

            var ifExpr = BuildRelationUpdateBlock(fromKey, fromProp, toEntity, toProp, varFromEntity, varDict);

            var forEachExpr = MakeForEach(varFromArr, varFromEntity, ifExpr);

            var codeBlock = Expression.Block(
                new[] { varFromArr, varToArr, varDict },
                varFromArrAssign, varToArrAssign, varDictAssignExpr, forEachExpr);

            return(toEnumType.IsAssignableFrom(memberExpr.Type)
                ? Expression.Lambda(codeBlock, fromParam, toParam)
                : Expression.Lambda(codeBlock, toParam, fromParam));
        }