/// <summary> /// Add a projection to the query. /// </summary> /// <param name="expression">Select method call expression.</param> private void AddProjection(MethodCallExpression expression) { // We only support Select(x => ...) projections. Anything else // will throw a NotSupportException. if (expression != null && expression.Arguments.Count == 2) { LambdaExpression projection = StripQuote(expression.Arguments[1]) as LambdaExpression; if (projection != null && projection.Parameters.Count == 1) { // Store the type of the input to the projection as we'll // need that for deserialization of values (since the // projection will change the expected type of the data // source) this.query.ProjectionArgumentType = projection.Parameters[0].Type; // Compile the projection into a function that we can apply // to the deserialized value to transform it accordingly. this.query.Projection = projection.Compile(); // Filter the selection down to just the values used by // the projection VisitorHelper.VisitMembers( projection.Body, (expr, recur) => { // Ensure we only process members of the parameter if (expr != null && expr.Expression.NodeType == ExpressionType.Parameter) { SerializableMember member = SerializableType.GetMember(expr.Member); if (member != null) { query.Selection.Add(member.Name); } } return(recur(expr)); }); // Make sure we also include all the members that would be // required for deserialization foreach (SerializableMember member in SerializableType.Get(this.query.ProjectionArgumentType) .Members .Select(p => p.Value) .Where(m => m.IsRequired)) { if (!this.query.Selection.Contains(member.Name)) { this.query.Selection.Add(member.Name); } } return; } } ThrowForUnsupportedException(expression); }
/// <summary> /// Returns the MemberExpressions in the expression hierarchy of the <paramref name="expression"/>. /// </summary> /// <param name="expression">The expression to search for children MemberExpressions</param> /// <returns>A collection of MemberExpressions.</returns> public IEnumerable <MemberExpression> GetMemberExpressions(Expression expression) { List <MemberExpression> members = new List <MemberExpression>(); VisitorHelper.VisitMembers( expression, (expr, recur) => { // Ensure we only process members of the parameter if (expr is MemberExpression) { members.Add((MemberExpression)expr); } return(recur(expr)); }); return(members); }