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." ); } }
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)); }
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)); }