linq 动态排序,不使用反射

时间:2023-03-08 19:02:30

之前网上搜索的相关方法都是使用了反射的方法来动态获取字段,以实现动态linq排序,但是因为项目组觉得此方法效率低下,所以不予采纳。

所以有了以下代码

 public interface IBase{
dynamic GetField(string field);
} public class Employee : IBase
{
public int ID { get; set; }
public string FName { get; set; }
public int Age { get; set; }
public char Sex { get; set; } public dynamic GetField(string field)
{
switch (field.ToUpper()) {
case "ID":
return ID;
case "FNAME":
return FName;
case "AGE":
return Age;
case "SEX":
return Sex;
default:
return ID;
}
}
}

  这是实体类,缺点是必须实现接口方法GetField,但这也是重点。

以下是对应的排序方法

/// <summary>
/// 对结果集进行排序
/// </summary>
/// <param name="source">结果集</param>
/// <param name="dict">参数列表KEY:OrderBy Ascending VALUE:以,分隔</param>
/// <returns></returns>
protected List<IBase> OrderBy(List<IBase> source, Dictionary<string, string> dict)
{
if (dict.ContainsKey("OrderBy"))
{
try
{
string[] Order = dict["OrderBy"].Split(',');
string[] ascend = dict.ContainsKey("Ascending") ? dict["Ascending"].Split(',') : new string[] { "1" };
IOrderedEnumerable<IBase> current = null;
if (ascend[0] == "1")
current = source.OrderBy(p => p.GetField(Order[0]));
else
current = source.OrderByDescending(p => p.GetField(Order[0])); int index = 0;
for (int i = 1; i < Order.Length; i++)
{
index = ascend.Length > i ? i : ascend.Length - 1;
if (ascend[index] == "1")
current = current.ThenBy(p => p.GetField(Order[i]));
else
current = current.ThenByDescending(p => p.GetField(Order[i]));
} return current.ToList();
}
catch { }
}
return source;
}

  以下是测试方法

public void LinqOrder()
{
var empList = new List<Employee>();
Random r = new Random();
int length = 10000000; Console.WriteLine(string.Format("开始装载数据({0})...", length));
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < length; i++)
{
empList.Add(new Employee()
{
ID = i,
FName = "A" + i,
Age = r.Next(0, 100),
Sex = r.Next(0, 1) == 1 ? 'F' : 'M'
});
}
sw.Stop();
Console.WriteLine(string.Format("{0}条数据装载完成,时间为:{1}", length, sw.ElapsedMilliseconds)); Console.WriteLine("开始转换数据,Employee to IBase");
sw = new Stopwatch();
sw.Start();
var list = empList.ToList<IBase>();
sw.Stop();
Console.WriteLine(string.Format("{0}条数据转换,Employee to IBase,时间为:{1}", length, sw.ElapsedMilliseconds)); Dictionary<string, string> dict = new Dictionary<string, string>();
dict["OrderBy"] = "Age,Sex";
dict["Ascending"] = "1,1";
Console.WriteLine("开始排序");
sw = new Stopwatch();
sw.Start();
OrderBy(list, dict);
sw.Stop();
Console.WriteLine(string.Format("{0}条数据使用dynamic排序时间为:{1}", length, sw.ElapsedMilliseconds)); Console.WriteLine("开始普通排序");
sw = new Stopwatch();
sw.Start();
empList.OrderBy(p => p.Age).ThenBy(p => p.Sex).ToList();
sw.Stop();
Console.WriteLine(string.Format("{0}条数据使用字段排序时间为:{1}", length, sw.ElapsedMilliseconds));
}

  以下是测试结果linq 动态排序,不使用反射