1

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?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
AgentFire
  • 8,944
  • 8
  • 43
  • 90

2 Answers2

0

I'm not exactly sure what you want - but this should help you get started at least (also check the other answers, suggestions - i.e. the dynamic linq)
(I'd still suggest you use a proper tool for that - http://nuget.org/packages/DynamicLINQ/)

It's a post I did earlier on (more of an exercise):
Converting List<string> to EntityFramework column/field list

What it does is to construct the expressions based on the string - for a very simple scenario of Select. You can use it like...

public static IEnumerable<object> 
    SelectAsEnumerable(this IQueryable entitySet, params string[] propertyPath)
{
    return entitySet.SelectDynamic(propertyPath) as IEnumerable<object>;
}
var list = db.YourEntity.SelectAsEnumerable("Name", "ID", "TestProperty.ID").ToList();

You'd need some more work to get what you want - e.g. add better parsing and more features etc. (also this works for Select - not OrderBy etc.)

Community
  • 1
  • 1
NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51
0

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);
}
AgentFire
  • 8,944
  • 8
  • 43
  • 90
  • 1
    Note that almost none of the query providers out there will know how to translate `Invoke` meaningfully. They'll just error out at runtime. – Servy Jan 30 '15 at 17:59
  • @Servy You are so wrong. Linq-to-sql translates it without a question. The code is in production for like 1.5 years already. You should give a try before downvoting. – AgentFire Jan 30 '15 at 18:33
  • I said most, not all. It is basically the only query provider out there, besides the LINQ to objects query provider, that will translate this meaningfully. It will break on just about every other one. There is nothing anywhere in this question to indicate that it is LINQ to SQL specific. – Servy Jan 30 '15 at 18:36
  • @Servy try EF provider then. – AgentFire Jan 31 '15 at 14:22
  • EF will not be able to properly translate this. It will throw a not supported exception. – Servy Feb 02 '15 at 14:55
  • @Servy do you have any solutions for the EF provider, then? – AgentFire Feb 02 '15 at 15:07
  • 1
    Yep; this will in fact work with any query provider: http://stackoverflow.com/questions/25935740/adding-expression-argument-as-property-in-linq-to-entities – Servy Feb 02 '15 at 15:12