从属性路径构建Lambda表达式

时间:2010-11-02 13:03:10

标签: linq lambda

嗨,我可以说我有一个看起来像这样的属性路径

我们可以说我有一篇文章有​​一个Vat和Vat有一个值。 现在我想使用Linq使用该属性路径对列表进行排序 当我在字符串中有“Vat.Value”并且我想要以下结果时,如何构建该lambda表达式

list.Order(x => x.Vat.Value)

我不会总是知道Vat和Value的类型,有时它只是我想要的x.Name。

3 个答案:

答案 0 :(得分:2)

我用扩展方法修复了它。现在使用属性路径的方法是例如

var orderedArticles = articles.OrderBy("Vat.Value");

而不是

var orderedArticles = articles.OrderBy(x => x.Vat.Value)

扩展方法:

private static Func<T, TReturnType> GetLambda<T, TReturnType>(IEnumerable<string> propertyNames)
{
    var rootParameterExression = Expression.Parameter(typeof(T));

    Expression expression = rootParameterExression;
    foreach (var propertyName in propertyNames)
    {
        expression = Expression.Property(expression, propertyName);
    }
    return Expression.Lambda<Func<T, TReturnType>>(expression, rootParameterExression).Compile();
}

public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> queryable, string propertyPath)
{
    var propertyPathList = propertyPath.Split(Convert.ToChar("."));
    Type propertyType = typeof(T);
    foreach (var propertyName in propertyPathList)
    {
        propertyType = propertyType.GetProperty(propertyName).PropertyType;
    }

    if(propertyType == typeof(decimal))
    {
        var lambda = GetLambda<T, Decimal>(propertyPathList);
        return queryable.OrderBy(lambda);
    }
    var lamda = GetLambda<T, object>(propertyPathList);
    return queryable.OrderBy(lamda);
}

答案 1 :(得分:1)

是否有理由不能使用现有的LINQ动态查询库,它具有带字符串的重载?

http://msdn.microsoft.com/en-us/vcsharp/bb894665.aspx

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

它可能正在做你刚才写的相同的事情,但它的代码你不需要维护并且可能有一些优化。

答案 2 :(得分:0)

我不确定我完全理解这个问题,但这样的事情看起来就像你想要的那样。请注意,为了清晰起见,我可能会将lambda重构为生成中的辅助方法。另请注意,使用这样的反射可能会显着影响性能,具体取决于您的集合的大小。

[Test]
public void OrderByUsingReflection()
{
    var values = new[] 
    {
        new { Vat = new { Value = "two"}},
        new { Vat = new {Value = "one"}},
    };

    var result = values.OrderBy(x =>
    {
        var vat = x.GetType().GetProperty("Vat").GetValue(x, null);
        return vat.GetType().GetProperty("Value").GetValue(vat, null);
    });

    Assert.AreEqual(result.ToList()[0], values[1]);
    Assert.AreEqual(result.ToList()[1], values[0]);
}