Complete definition of my extension method goes first.
static IQueryable<TResult> WithTicketNumbers<T, TResult>(
this IQueryable<T> q,
Expression<Func<T, Ticket>> ticketSelector,
Expression<Func<T, string, TResult>> resultSelector,
int digitsCount)
I have this IQueryable<T> q
sequence, which is the target of the extension.
This method takes tickets from q
selected by ticketSelector
:
var tickets = q.Select(ticketSelector);
Next, and the main goal of the method, is taking some string
-linq-supported-info from Ticket
class and projecting both Ticket
and string
info next to the sequence:
var tickets2 = tickets.Select(W => new { Ticket = W, Info = W.Name + "123"});
Finally, I want my method to return an IQueryable
which will select what user wants in resultSelector
. This result selector picks both the ticket and the info parameters and produces what user wants it to produce. I am kind of stuck with the Expression
class to create appropriate expression.
So far, I got my two parameters:
ParameterExpression tParameter = Expression.Parameter(typeof(T));
ParameterExpression stringParameter = Expression.Parameter(typeof(string));
Also, as I think, the final lambda:
Expression<Func<T, string, TResult>> lambda =
Expression.Lambda<Func<T, string, TResult>>
(/* ? */, tParameter, stringParameter);
However, I cannot figure out the body.
I can do Expression.Property
to by reflection get the two properties Ticket
and Info
, but there is a type required, and I have anonymous type there, in tickets2
.
Next, (as I guess) I need to use that lambda
inside the tickets2
to produce the method result IQueryable<TResult>
.
So how should I build that final expression?
Solved:
/// <summary>
/// Returns a queryable sequence of TResult elements which is composed through specified property evaluation.
/// </summary>
public static IQueryable<TResult> WithInfo<TItem, TProperty, TResult>(this IQueryable<TItem> q, Expression<Func<TItem, TProperty>> propertySelector, Expression<Func<TItem, TProperty, TResult>> resultSelector)
{
ParameterExpression param = Expression.Parameter(typeof(TItem));
InvocationExpression prop = Expression.Invoke(propertySelector, param);
var lambda = Expression.Lambda<Func<TItem, TResult>>(Expression.Invoke(resultSelector, param, prop), param);
return q.Select(lambda);
}