使用自定义参数选择构建LambdaExpression

时间:2013-04-19 11:45:03

标签: c# lambda expression-trees iqueryable

我的扩展方法的完整定义是第一位的。

static IQueryable<TResult> WithTicketNumbers<T, TResult>(
    this IQueryable<T> q,
    Expression<Func<T, Ticket>> ticketSelector,
    Expression<Func<T, string, TResult>> resultSelector,
    int digitsCount)

我有这个IQueryable<T> q序列,这​​是扩展的目标。

此方法从q选择的ticketSelector获取门票:

var tickets = q.Select(ticketSelector);

接下来,该方法的主要目标是从string类中获取一些Ticket - linq-supported-info,并预测Ticketstring信息到序列:

var tickets2 = tickets.Select(W => new { Ticket = W, Info = W.Name + "123"});

最后,我希望我的方法返回IQueryable,它会在resultSelector中选择用户想要的内容。此结果选择器选择票证和info参数,并生成用户希望它生成的内容。我有点坚持Expression类来创建适当的表达式。

到目前为止,我得到了两个参数:

ParameterExpression tParameter = Expression.Parameter(typeof(T));
ParameterExpression stringParameter = Expression.Parameter(typeof(string));

另外,正如我所想,最后的lambda:

Expression<Func<T, string, TResult>> lambda =
    Expression.Lambda<Func<T, string, TResult>>
    (/* ? */, tParameter, stringParameter);

然而,我无法弄明白身体。

我可以通过反射Expression.Property来获取两个属性TicketInfo,但是需要一个类型,我在tickets2中有匿名类型

接下来,(我猜)我需要在lambda内使用tickets2来生成方法结果IQueryable<TResult>

那么我应该如何构建最终表达式呢?

2 个答案:

答案 0 :(得分:0)

我不确定你想要什么 - 但这应该有助于你至少开始(也检查其他答案,建议 - 即dynamic linq
(我仍然建议您使用适当的工具 - http://nuget.org/packages/DynamicLINQ/

  

这是我之前做过的一篇文章(更多的是练习):
  Converting List<string> to EntityFramework column/field list

它的作用是基于字符串构造表达式 - 用于Select的非常简单的场景。你可以像......一样使用它。

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();

您需要更多工作才能获得所需内容 - 例如添加更好的parsing和更多功能等(这也适用于Select - 而不是OrderBy等。

答案 1 :(得分:0)

解决:

/// <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);
}