/// <summary> /// Constructs a <see cref="LambdaExpression"/> that is able to extract a specific simple <paramref name="searchedExpression"/> from a /// complex <paramref name="fullExpression"/>. /// </summary> /// <param name="searchedExpression">The expression an accessor to which should be created.</param> /// <param name="fullExpression">The full expression containing the <paramref name="searchedExpression"/>.</param> /// <param name="inputParameter">The input parameter to be used by the resulting lambda. Its type must match the type of <paramref name="fullExpression"/>.</param> /// <remarks>The <see cref="AccessorFindingExpressionTreeVisitor"/> compares the <paramref name="searchedExpression"/> via reference equality, /// which means that exactly the same expression reference must be contained by <paramref name="fullExpression"/> for the visitor to return the /// expected result. In addition, the visitor can only provide accessors for expressions nested in <see cref="NewExpression"/> or /// <see cref="MemberInitExpression"/>.</remarks> /// <returns>A <see cref="LambdaExpression"/> acting as an accessor for the <paramref name="searchedExpression"/> when an input matching /// <paramref name="fullExpression"/> is given. /// </returns> public static LambdaExpression FindAccessorLambda(Expression searchedExpression, Expression fullExpression, ParameterExpression inputParameter) { ArgumentUtility.CheckNotNull("searchedExpression", searchedExpression); ArgumentUtility.CheckNotNull("fullExpression", fullExpression); ArgumentUtility.CheckNotNull("inputParameter", inputParameter); if (inputParameter.Type != fullExpression.Type) { throw new ArgumentException( string.Format("The inputParameter's type '{0}' must match the fullExpression's type '{1}'.", fullExpression.Type, inputParameter.Type), "inputParameter"); } var visitor = new AccessorFindingExpressionTreeVisitor(searchedExpression, inputParameter); visitor.VisitExpression(fullExpression); if (visitor.AccessorPath != null) { return(visitor.AccessorPath); } else { var message = string.Format( "The given expression '{0}' does not contain the searched expression '{1}' in a nested NewExpression with member assignments or a " + "MemberBindingExpression.", FormattingExpressionTreeVisitor.Format(fullExpression), FormattingExpressionTreeVisitor.Format(searchedExpression)); throw new ArgumentException(message, "fullExpression"); } }
protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) { ArgumentUtility.CheckNotNull("expression", expression); try { var accessorLambda = AccessorFindingExpressionTreeVisitor.FindAccessorLambda(expression, _itemExpression, _lambdaParameter); return(accessorLambda.Body); } catch (ArgumentException ex) { var message = string.Format( "Cannot create a LambdaExpression that retrieves the value of '{0}' from items with a structure of '{1}'. The item expression does not " + "contain the value or it is too complex.", FormattingExpressionTreeVisitor.Format(expression), FormattingExpressionTreeVisitor.Format(_itemExpression)); throw new InvalidOperationException(message, ex); } }