2010-11-02 31 views
1

嗨可以说我有一个属性路径看起来像这样构建从一个的PropertyPath Lambda表达式

我们可以说,我有一个具有还原的文章和增值税有一个值。 现在我想使用Linq使用属性路径 我怎样才能建立一个lambda表达式时,我在字符串中有“Vat.Value”排序名单,我想下面的结果

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

我不会总是知道增值税和价值的类型,有时只有我出去的x.Name。

回答

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]); 
} 
+0

我认为我现在发布的那个更高效,更易于使用。 – NPehrsson 2010-11-02 20:22:59

1

我用扩展方法修复了它。该方法使用的PropertyPath现在例如

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