编辑:将代码更改为与您的语法更接近
此代码在客户端上进行排序,但适用于所有IEnumerables
。如果您绝对需要在数据库上进行排序,请查看Yacoub的static MyClass()
以了解他是如何解决这个问题的。
下面的示例基于您提供的信息,您可能需要稍微调整一下。
public class DemoClass
{
public DateTime Created { get; set; }
public bool Approved { get; set; }
public Person Author { get; set; }
}
public class Person
{
public string Name { get; set; }
}
由于您的示例包含实际解析为Author.Name
的author
,因此您需要为关键字创建某种映射(就像您的OrderExpression
类一样)。
public class OrderExpressions<T>
{
private readonly Dictionary<string,Func<T,object>> _mappings =
new Dictionary<string,Func<T, object>>();
public OrderExpressions<T> Add(Func<T, object> expression, string keyword)
{
_mappings.Add(keyword, expression);
return this;
}
public Func<T, object> this[string keyword]
{
get { return _mappings[keyword]; }
}
}
这可以像这样使用:
OrderExpressions<DemoClass> expressions = new OrderExpressions<DemoClass>()
.Add(x => x.Created, "created")
.Add(x => x.Approved, "approved")
.Add(x => x.Author.Name, "author");
你可以直接将这些函数/lambda表达式传递给Linq,并在一起添加下一个比较。从
OrderBy
或
OrderByDescrending
开始,这将为您提供第一个
IOrderedEnumerable
,然后使用
ThenBy
或
ThenByDescending
添加所有剩余的参数。
public static class KeywordSearchExtender
{
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> data,
OrderExpressions<T> mapper, params string[] arguments)
{
if (arguments.Length == 0)
throw new ArgumentException(@"You need at least one argument!", "arguments");
List<SortArgument> sorting = arguments.Select(a => new SortArgument(a)).ToList();
IOrderedEnumerable<T> result = null;
for (int i = 0; i < sorting.Count; i++)
{
SortArgument sort = sorting[i];
Func<T, object> lambda = mapper[sort.Keyword];
if (i == 0)
result = sorting[i].Ascending ?
data.OrderBy(lambda) :
data.OrderByDescending(lambda);
else
result = sorting[i].Ascending ?
result.ThenBy(lambda) :
result.ThenByDescending(lambda);
}
return result;
}
}
public class SortArgument
{
public SortArgument()
{ }
public SortArgument(string term)
{
if (term.StartsWith("-"))
{
Ascending = false;
Keyword = term.Substring(1);
}
else if (term.StartsWith("+"))
{
Ascending = true;
Keyword = term.Substring(1);
}
else
{
Ascending = true;
Keyword = term;
}
}
public string Keyword { get; set; }
public bool Ascending { get; set; }
}
全部一起使用的方式如下:
var data = WhateverYouDoToGetYourData();
var expressions = new OrderExpressions<DemoClass>()
.Add(x => x.Created, "created")
.Add(x => x.Approved, "approved")
.Add(x =>x.Author.Name, "author");
var result = data.OrderBy(expressions, "+created", "-approved", "+author");
var result = data.OrderBy(expressions, fields);
你可以在dotNetFiddle上找到我的概念证明。