大家。在过去的几个小时里,我尝试使用立即窗口找到Google的答案和绝望的测试,但我认为我没有提出正确的问题。
我的应用程序中有一个OrderByExtender,我只使用属性名称和布尔来判断它是ASC还是DESC排序。
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, string key, bool isAscending)
{
LambdaExpression sortLambda = BuildLambda<T>(key);
if (isAscending)
return collection.OrderBy((Func<T, object>)sortLambda.Compile());
else
return collection.OrderByDescending((Func<T, object>)sortLambda.Compile());
}
private static LambdaExpression BuildLambda<T>(string key)
{
ParameterExpression TParameterExpression = Expression.Parameter(typeof(T), "p");
LambdaExpression sortLambda = Expression.Lambda(Expression.Convert(Expression.Property(TParameterExpression, key), typeof(object)), TParameterExpression);
return sortLambda;
}
当我使用common-type属性(string,int等)时,它就像一个魅力。但现在我想出了以下场景:我有一个名为 BusinessOrder 的对象,其中有一个类型为 Quarter 的属性。此Quarter对象有三个属性:Year(int),Quarter(int)和缩写(string)。我必须使用缩写属性来执行OrderBy。换句话说,我必须这样做:
BusinessOrderList.OrderBy(b => b.Quarter.Abbreviation);
但是我想把这种可能性放在我的Extender中,通过传递键参数,例如“Quarter.Abbreviation”,Extender方法理解这是将属性放入内部的问题一个“复杂的对象”。
我相信我可以在“Expression.Lambda”方法中创建 sortLambda 变量,但我无法弄清楚如何使用Expressions复制此行为。有人能帮我吗?提前谢谢。
答案 0 :(得分:2)
您无法一步访问复杂属性。您必须递归地构建表达式链:
private Func<TInput, object> BuildLambda<TInput>(string complexPropertyPath)
{
var parameter = Expression.Parameter(typeof(TInput), "p");
var propertyPathParts = complexPropertyPath.Split('.');
MemberExpression complexPropertyAccessExpression = null;
foreach (var propertyPathPart in propertyPathParts)
{
complexPropertyAccessExpression = complexPropertyAccessExpression == null
? Expression.Property(parameter, propertyPathPart)
: Expression.Property(complexPropertyAccessExpression, propertyPathPart);
}
var lambda = (Func<TInput, object>)Expression.Lambda(complexPropertyAccessExpression, parameter).Compile();
return lambda;
}
答案 1 :(得分:0)
如果可能,我建议您使用string key
参数替换Expression<Func<T, object>> key
参数。这样,您的函数调用就像您描述的那样BusinessOrderList.OrderBy(b => b.Quarter.Abbreviation);
。由于所有OrderBy / OrderByDescending方法都接受此表达式作为字符串的替代方法,因此我不认为将key
保留为字符串会带来什么好处。
答案 2 :(得分:0)
您可以传递Func
来整理您的收藏
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> collection,
Func<IEnumerable<T>,IOrderedEnumerable<T>> OrderBy)
{
if(OrderBy != null)
return OrderBy(collection);
return collection;
}
你必须像这样称呼它
{
Func<IEnumerable<Book>,IOrderedEnumerable<Book>> sort =
list => list.OrderBy(B=>B.Author.Name).ThenByDescending(B=>B.Title) ;
List.OrderBy(sort);
}