之前網上搜索的相關方法都是使用了反射的方法來動態獲取字段,以實現動態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)); }
以下是測試結果