예제 #1
0
        private Expression VisitMapContextCall(MethodCallExpression node)
        {
            switch (node.Method.Name)
            {
            case "Map": {
                var inPrm   = node.Arguments[0];
                var inType  = inPrm.Type;
                var outType = node.Method.ReturnType;

                if (_includes != null && !CheckInclude(inPrm))
                {
                    return(Expression.Default(outType));
                }

                var mapDefinition = _mapConfiguration.GetMapDefinition(inType, outType);
                var projector     = mapDefinition.Projector;
                var oldInPrm      = projector.Parameters[0];

                var memberInit    = (MemberInitExpression)projector.Body;
                var replaceParams = new Dictionary <ParameterExpression, Expression> {
                    { oldInPrm, inPrm }
                };
                var parameterReplaceVisitor = new ParameterReplaceVisitor(replaceParams);

                return(Visit(parameterReplaceVisitor.Visit(memberInit)));
            }

            case "MapToList": {
                var retType = node.Method.ReturnType;
                var inPrm   = node.Arguments[0];
                var genPrms = node.Method.GetGenericArguments();
                var inType  = genPrms[0];
                var outType = genPrms[1];

                IncludePath memberIncludePath = null;
                if (_includes != null && !TryGetIncludePath(inPrm, out memberIncludePath))
                {
                    return(Expression.Default(retType));
                }

                var mapDefinition = _mapConfiguration.GetMapDefinition(inType, outType);
                var subValue      = new ProjectionVisitor(_mapConfiguration, memberIncludePath?.Children).VisitProjector(mapDefinition.Projector);
                var methodName    = node.Method.Name.Substring(3);
                var subProjector  = Expression.Call(typeof(Enumerable), "Select", new[] {
                        node.Method.GetGenericArguments()[0],
                        node.Method.GetGenericArguments()[1]
                    }, node.Arguments[0], subValue);

                return(Expression.Call(typeof(Enumerable), methodName, new[] { node.Method.ReturnType.GetGenericArguments()[0] }, subProjector));
            }

            default:
                throw new InvalidOperationException(
                          $"Projection does not support MapContext method '{node.Method.Name}', only 'Map' and 'MapToList' are supported."
                          );
            }
        }
예제 #2
0
        internal Expression <Func <TIn, MapContext, TOut> > GetProjector()
        {
            var inObjPrm      = Expression.Parameter(_inType);
            var mapContextPrm = Expression.Parameter(typeof(MapContext));

            var memberBindings = new List <MemberBinding>();

            foreach (var outMember in _outMembers)
            {
                LambdaExpression expression;
                if (_expressions.TryGetValue(outMember, out expression))
                {
                    if (expression == null)
                    {
                        continue;
                    }

                    var prv = new ParameterReplaceVisitor(new Dictionary <ParameterExpression, Expression> {
                        { expression.Parameters[0], inObjPrm },
                        { expression.Parameters[1], mapContextPrm }
                    });
                    memberBindings.Add(Expression.Bind(outMember.MemberInfo, prv.Visit(expression.Body)));
                }
                else
                {
                    var memberBinding = CreateMemberBinding(outMember, inObjPrm, mapContextPrm);
                    if (memberBinding != null)
                    {
                        memberBindings.Add(memberBinding);
                    }
                }
            }

            var memberInit = Expression.MemberInit(Expression.New(_outType), memberBindings);

            return(Expression.Lambda <Func <TIn, MapContext, TOut> >(memberInit, inObjPrm, mapContextPrm));
        }
예제 #3
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.DeclaringType == typeof(MapContext) && node.Method.Name == "Map")
            {
                var inPrm   = node.Arguments[0];
                var inType  = inPrm.Type;
                var outType = node.Method.ReturnType;

                if (_includes != null)
                {
                    var path = Helper.GetMemberPath(inPrm as MemberExpression);
                    if (path.Any() && GetIncludePath(path) == null)
                    {
                        return(Expression.Default(outType));
                    }
                }

                var mapDefinition = _mapConfiguration.GetMapDefinition(inType, outType);
                var projector     = mapDefinition.Projector;
                var oldInPrm      = projector.Parameters[0];

                var memberInit    = (MemberInitExpression)projector.Body;
                var replaceParams = new Dictionary <ParameterExpression, Expression> {
                    { oldInPrm, inPrm }
                };
                var parameterReplaceVisitor = new ParameterReplaceVisitor(replaceParams);
                return(base.Visit(parameterReplaceVisitor.Visit(memberInit)));
            }
            else if (node.Method.DeclaringType == typeof(MapContext) && node.Method.Name == "MapToList")
            {
                var retType = node.Method.ReturnType;
                var inPrm   = node.Arguments[0];
                var genPrms = node.Method.GetGenericArguments();
                var inType  = genPrms[0];
                var outType = genPrms[1];

                IncludePath memberIncludePath = null;
                if (_includes != null)
                {
                    memberIncludePath = GetIncludePath(Helper.GetMemberPath(inPrm as MemberExpression));
                    if (memberIncludePath == null)
                    {
                        return(Expression.Default(retType));
                    }
                }

                var mapDefinition = _mapConfiguration.GetMapDefinition(inType, outType);
                var subValue      = new ProjectionVisitor(_mapConfiguration, memberIncludePath?.Children).VisitProjector(mapDefinition.Projector);
                var subProjector  = Expression.Call(typeof(Enumerable), "Select", new Type[] {
                    node.Method.GetGenericArguments()[0],
                    node.Method.GetGenericArguments()[1]
                }, node.Arguments[0], subValue);
                return(Expression.Call(typeof(Enumerable), "ToList", new Type[] { node.Method.ReturnType.GetGenericArguments()[0] }, subProjector));
            }
            else if (node.Method.DeclaringType == typeof(Enumerable) && node.Method.Name == "ToList")
            {
                var retType = node.Method.ReturnType;

                var subNode = node.Arguments[0] as MethodCallExpression;
                if (subNode != null && subNode.Method.DeclaringType == typeof(Enumerable) && subNode.Method.Name == "Select")
                {
                    var inPrm = subNode.Arguments[0];

                    IncludePath memberIncludePath = null;
                    if (_includes != null)
                    {
                        memberIncludePath = GetIncludePath(Helper.GetMemberPath(inPrm as MemberExpression));
                        if (memberIncludePath == null)
                        {
                            return(Expression.Default(retType));
                        }
                    }

                    var subValue     = new ProjectionVisitor(_mapConfiguration, memberIncludePath?.Children).Visit(subNode.Arguments[1]);
                    var subProjector = Expression.Call(typeof(Enumerable), "Select", new Type[] {
                        subNode.Method.GetGenericArguments()[0],
                        subNode.Method.GetGenericArguments()[1]
                    }, subNode.Arguments[0], subValue);
                    return(Expression.Call(typeof(Enumerable), "ToList", new Type[] { node.Method.ReturnType.GetGenericArguments()[0] }, subProjector));
                }
            }

            return(base.VisitMethodCall(node));
        }