예제 #1
0
        protected override void CompileInternal()
        {
            if (ResultMapFunction != null)
            {
                return;
            }

            var destVariable = GetDestionationVariable();

            ProcessCustomMembers();
            ProcessCustomFunctionMembers();
            ProcessFlattenedMembers();
            ProcessAutoProperties();

            CreateQueryableProjection();

            var expressions = new List <Expression> {
                destVariable
            };

            if (BeforeMapHandler != null)
            {
                Expression <Action <T, TN> > beforeExpression = (src, dest) => BeforeMapHandler(src, dest);
                var beforeInvokeExpr = Expression.Invoke(beforeExpression, SourceParameter, destVariable.Left);
                expressions.Add(beforeInvokeExpr);
            }

            expressions.AddRange(PropertyCache.Values);

            var customProps = CustomPropertyCache.Where(k => !IgnoreMemberList.Contains(k.Key)).Select(k => k.Value);

            expressions.AddRange(customProps);

            if (AfterMapHandler != null)
            {
                Expression <Action <T, TN> > afterExpression = (src, dest) => AfterMapHandler(src, dest);
                var afterInvokeExpr = Expression.Invoke(afterExpression, SourceParameter, destVariable.Left);
                expressions.Add(afterInvokeExpr);
            }

            ResultExpressionList.AddRange(expressions);
            expressions.Add(destVariable.Left);

            var variables = new List <ParameterExpression>();

            var finalExpression = Expression.Block(variables, expressions);

            var destExpression = destVariable.Left as ParameterExpression;

            var substituteParameterVisitor =
                new PreciseSubstituteParameterVisitor(
                    new KeyValuePair <ParameterExpression, ParameterExpression>(SourceParameter, SourceParameter),
                    new KeyValuePair <ParameterExpression, ParameterExpression>(destExpression, destExpression));

            var resultExpression = substituteParameterVisitor.Visit(finalExpression) as BlockExpression;

            var expression = Expression.Lambda <Func <T, TN, TN> >(resultExpression, SourceParameter, DestFakeParameter);

            ResultMapFunction = expression.Compile();
        }
        public override BlockExpression MapProperty(Type srcType, Type destType, Expression srcExpression, Expression destExpression)
        {
            var sourceVariable = Expression.Variable(srcType,
                                                     string.Format("{0}_{1}Src", srcType.Name, Guid.NewGuid().ToString().Replace("-", "_")));

            var assignSourceFromProp = Expression.Assign(sourceVariable, srcExpression);

            var mapExpressions = GetMapExpressions(srcType, destType);
            var mapExprForType = mapExpressions.Item1;
            var destVariable   = Expression.Variable(destType,
                                                     string.Format("{0}_{1}Dst", destType.Name,
                                                                   Guid.NewGuid().ToString().Replace("-", "_")));
            var assignDestFromProp = Expression.Assign(destVariable, destExpression);

            var ifDestNull = destType.IsPrimitive || destType.IsEnum ? (Expression)StaticExpressions.FalseConstant : Expression.Equal(destExpression, StaticExpressions.NullConstant);

            var newDestInstanceExp = mapExprForType[0] as BinaryExpression;

            if (newDestInstanceExp != null)
            {
                mapExprForType.RemoveAt(0);

                var destVar = newDestInstanceExp.Left as ParameterExpression;

                var assignExistingDestExp = Expression.Assign(destVar, destExpression);

                var destCondition = Expression.IfThenElse(ifDestNull, newDestInstanceExp, assignExistingDestExp);
                mapExprForType.Insert(0, destCondition);
            }

            var blockForSubstitution = Expression.Block(mapExprForType);
            var substBlock           =
                new PreciseSubstituteParameterVisitor(
                    new KeyValuePair <ParameterExpression, ParameterExpression>(mapExpressions.Item2, sourceVariable),
                    new KeyValuePair <ParameterExpression, ParameterExpression>(mapExpressions.Item3, destVariable))
                .Visit(blockForSubstitution) as
                BlockExpression;

            //var substBlock =
            //    new SubstituteParameterVisitor(sourceVariable, destVariable).Visit(blockForSubstitution) as
            //        BlockExpression;
            var resultMapExprForType = substBlock.Expressions;

            var assignExp = Expression.Assign(destExpression, destVariable);

            var expressions = new List <Expression> {
                assignSourceFromProp, assignDestFromProp
            };

            expressions.AddRange(resultMapExprForType);
            expressions.Add(assignExp);

            var parameterExpressions = new List <ParameterExpression> {
                sourceVariable, destVariable
            };
            var blockExpression = Expression.Block(parameterExpressions, expressions);

            return(blockExpression);
        }
예제 #3
0
        protected override void CompileInternal()
        {
            if (this.ResultMapFunction != null)
            {
                return;
            }

            this.ProcessCustomMembers();
            this.ProcessCustomFunctionMembers();
            this.ProcessFlattenedMembers();
            this.ProcessAutoProperties();

            var expressions = new List <Expression>();

            if (this.BeforeMapHandler != null)
            {
                Expression <Action <T, TN> > beforeExpression = (src, dest) => this.BeforeMapHandler(src, dest);
                var beforeInvokeExpr = Expression.Invoke(beforeExpression, this.SourceParameter, this.DestFakeParameter);
                expressions.Add(beforeInvokeExpr);
            }

            expressions.AddRange(this.PropertyCache.Values);

            var customProps = this.CustomPropertyCache.Where(k => !this.IgnoreMemberList.Contains(k.Key)).Select(k => k.Value);

            expressions.AddRange(customProps);

            if (this.AfterMapHandler != null)
            {
                Expression <Action <T, TN> > afterExpression = (src, dest) => this.AfterMapHandler(src, dest);
                var afterInvokeExpr = Expression.Invoke(afterExpression, this.SourceParameter, this.DestFakeParameter);
                expressions.Add(afterInvokeExpr);
            }

            this.ResultExpressionList.AddRange(expressions);
            this.ResultExpressionList.Insert(0, this.GetDestionationVariable());

            expressions.Add(this.DestFakeParameter);

            var finalExpression = Expression.Block(expressions);

            var substituteParameterVisitor =
                new PreciseSubstituteParameterVisitor(
                    new KeyValuePair <ParameterExpression, ParameterExpression>(this.SourceParameter, this.SourceParameter),
                    new KeyValuePair <ParameterExpression, ParameterExpression>(this.DestFakeParameter, this.DestFakeParameter));

            //var substituteParameterVisitor = new SubstituteParameterVisitor(SourceParameter, DestFakeParameter);

            var resultExpression = substituteParameterVisitor.Visit(finalExpression);

            var expression = Expression.Lambda <Func <T, TN, TN> >(resultExpression, this.SourceParameter, this.DestFakeParameter);

            this.ResultMapFunction = expression.Compile();
        }
예제 #4
0
        public override BlockExpression MapProperty(Type srcType, Type destType, Expression srcExpression, Expression destExpression, bool newDest)
        {
            var sourceVariable = Expression.Variable(
                srcType,
                $"{srcType.Name}_{Guid.NewGuid().ToString().Replace("-", "_")}Src");
            var assignSourceFromProp = Expression.Assign(sourceVariable, srcExpression);
            var exprForType          = this.GetMapExpressions(srcType, destType);
            var mapExprForType       = exprForType.Item1;
            var destVariable         = Expression.Variable(
                destType,
                $"{destType.Name}_{Guid.NewGuid().ToString().Replace("-", "_")}Dst");
            var blockForSubstitution = Expression.Block(mapExprForType);

            var substBlock = new PreciseSubstituteParameterVisitor(
                new KeyValuePair <ParameterExpression, ParameterExpression>(
                    exprForType.Item2,
                    sourceVariable),
                new KeyValuePair <ParameterExpression, ParameterExpression>(
                    exprForType.Item3,
                    destVariable)).Visit(blockForSubstitution) as BlockExpression;

            //var substBlock =
            //    new SubstituteParameterVisitor(sourceVariable, destVariable).Visit(blockForSubstitution) as
            //        BlockExpression;
            var resultMapExprForType = substBlock.Expressions;

            var assignExp = Expression.Assign(destExpression, destVariable);

            var expressions = new List <Expression> {
                assignSourceFromProp
            };

            expressions.AddRange(resultMapExprForType);
            expressions.Add(assignExp);

            var parameterExpressions = new List <ParameterExpression> {
                sourceVariable, destVariable
            };
            var blockExpression = Expression.Block(parameterExpressions, expressions);

            return(blockExpression);
        }
예제 #5
0
        public Expression GetMemberMappingExpression(Expression left, Expression right)
        {
            var nullCheckNestedMemberVisitor = new NullCheckNestedMemberVisitor(false);

            nullCheckNestedMemberVisitor.Visit(right);

            var destNullableType   = Nullable.GetUnderlyingType(left.Type);
            var sourceNullableType = Nullable.GetUnderlyingType(right.Type);

            var destType   = destNullableType ?? left.Type;
            var sourceType = sourceNullableType ?? right.Type;

            if (ComplexMapCondition(sourceType, destType))
            {
                var customMapExpression = GetCustomMapExpression(right.Type, left.Type);
                if (customMapExpression != null)
                {
                    var srcExp = Expression.Variable(right.Type,
                                                     string.Format("{0}Src", Guid.NewGuid().ToString("N")));
                    var assignSrcExp = Expression.Assign(srcExp, right);

                    var destExp = Expression.Variable(left.Type,
                                                      string.Format("{0}Dst", Guid.NewGuid().ToString("N")));
                    var assignDestExp = Expression.Assign(destExp, left);

                    // try precise substitute visitor
                    var substituteParameterVisitor =
                        new PreciseSubstituteParameterVisitor(
                            new KeyValuePair <ParameterExpression, ParameterExpression>(
                                Expression.Variable(right.Type, "srcTyped"), srcExp),
                            new KeyValuePair <ParameterExpression, ParameterExpression>(
                                Expression.Variable(left.Type, "dstTyped"), destExp));

                    var blockExpression = substituteParameterVisitor.Visit(customMapExpression) as BlockExpression;

                    var assignResultExp = Expression.Assign(left, destExp);
                    var resultBlockExp  = Expression.Block(new[] { srcExp, destExp }, assignSrcExp, assignDestExp, blockExpression, assignResultExp);

                    var checkNullExp =
                        Expression.IfThenElse(Expression.Equal(right, Expression.Default(right.Type)),
                                              Expression.Assign(left, Expression.Default(left.Type)), resultBlockExp);

                    var releaseExp = Expression.Block(new ParameterExpression[] { }, checkNullExp);

                    return(releaseExp);
                }

                var returnTypeDifferenceVisitor = new ReturnTypeDifferenceVisitor(right);
                returnTypeDifferenceVisitor.Visit(right);

                // If right is custom member expression / func and return type matches left type
                // just assign
                if (left.Type == right.Type && returnTypeDifferenceVisitor.DifferentReturnTypes)
                {
                    return(Expression.Assign(left, right));
                }

                if (typeof(IConvertible).IsAssignableFrom(destType) &&
                    typeof(IConvertible).IsAssignableFrom(sourceType))
                {
                    var assignExp = CreateConvertibleAssignExpression(left,
                                                                      right,
                                                                      left.Type,
                                                                      sourceType,
                                                                      destNullableType);

                    return(assignExp);
                }
                var mapComplexResult = GetDifferentTypeMemberMappingExpression(right, left);

                return(nullCheckNestedMemberVisitor.CheckNullExpression != null
                    ? Expression.Condition(nullCheckNestedMemberVisitor.CheckNullExpression,
                                           Expression.Assign(left, Expression.Default(left.Type)),
                                           mapComplexResult)
                    : mapComplexResult);
            }
            var binaryExpression = CreateAssignExpression(left,
                                                          right,
                                                          left.Type,
                                                          destNullableType,
                                                          sourceNullableType);

            var conditionalExpression = nullCheckNestedMemberVisitor.CheckNullExpression != null?Expression.Condition(nullCheckNestedMemberVisitor.CheckNullExpression, Expression.Assign(left, Expression.Default(left.Type)), binaryExpression) : (Expression)binaryExpression;

            return(conditionalExpression);
        }
예제 #6
0
        protected override void CompileInternal()
        {
            if (this.ResultMapFunction != null)
            {
                return;
            }

            BinaryExpression destVariable = this.GetDestionationVariable();

            this.ProcessCustomMembers();
            this.ProcessCustomFunctionMembers();
            this.ProcessFlattenedMembers();
            this.ProcessAutoProperties();

            this.CreateQueryableProjection();

            List <Expression> expressions = new List <Expression> {
                destVariable
            };

            if (this.BeforeMapHandler != null)
            {
                Expression <Action <T, TN> > beforeExpression = (src, dest) => this.BeforeMapHandler(src, dest);
                InvocationExpression         beforeInvokeExpr = Expression.Invoke(beforeExpression, this.SourceParameter, destVariable.Left);
                expressions.Add(beforeInvokeExpr);
            }

            expressions.AddRange(this.PropertyCache.Values);

            IEnumerable <Expression> customProps = this.CustomPropertyCache.Where(k => !this.IgnoreMemberList.Contains(k.Key))
                                                   .Select(k => k.Value);

            expressions.AddRange(customProps);

            if (this.AfterMapHandler != null)
            {
                Expression <Action <T, TN> > afterExpression = (src, dest) => this.AfterMapHandler(src, dest);
                InvocationExpression         afterInvokeExpr = Expression.Invoke(afterExpression, this.SourceParameter, destVariable.Left);
                expressions.Add(afterInvokeExpr);
            }

            this.ResultExpressionList.AddRange(expressions);
            expressions.Add(destVariable.Left);

            List <ParameterExpression> variables = new List <ParameterExpression>();

            BlockExpression finalExpression = Expression.Block(variables, expressions);

            ParameterExpression destExpression = destVariable.Left as ParameterExpression;

            PreciseSubstituteParameterVisitor substituteParameterVisitor = new PreciseSubstituteParameterVisitor(
                new KeyValuePair <ParameterExpression, ParameterExpression>(this.SourceParameter, this.SourceParameter),
                new KeyValuePair <ParameterExpression, ParameterExpression>(destExpression, destExpression));

            BlockExpression resultExpression = substituteParameterVisitor.Visit(finalExpression) as BlockExpression;

            Expression <Func <T, TN, TN> > expression = Expression.Lambda <Func <T, TN, TN> >(
                resultExpression,
                this.SourceParameter,
                this.DestFakeParameter);

            this.ResultMapFunction = expression.Compile();
        }