0%

【Linq】Multiple Column with OrderBy

用Linq的好處是強型別,讓你在寫程式的時後不會因為Key錯字,但也有些衍伸的問題導致程式會寫得很醜,以前最常碰到的例子就是,當排序可能依據【多欄位】升降冪,程式就會又臭又長。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
void Main()
{
//要用來排序的欄位
OrderByColumnEnum OrderByColumn = OrderByColumnEnum.Pin;
//排序的方法
OrderByEnum OrderBy = OrderByEnum.ASC;

//準備資料
var BuildingList = new List<Building>();
for (int i = 0; i < 5; i++)
{
BuildingList.Add(new Building
{
Age = 1 * (i+1),
Pin = 1 * (i+1),
CaseDate = DateTime.Now.AddDays(i +1)
});
}

//排序欄位
switch (OrderByColumn)
{
case OrderByColumnEnum.Pin:
switch (OrderBy)
{
case OrderByEnum.ASC:
//因為裡面用到的欄位不同,又是強型別,只能寫死...
BuildingList = BuildingList.OrderBy(x => x.Pin).ToList();
break;
case OrderByEnum.DESC:
BuildingList = BuildingList.OrderByDescending(x => x.Pin).ToList();
break;
}
break;
case OrderByColumnEnum.Age:
switch (OrderBy)
{
case OrderByEnum.ASC:
BuildingList = BuildingList.OrderBy(x => x.Age).ToList();
break;
case OrderByEnum.DESC:
BuildingList = BuildingList.OrderByDescending(x =>x.Age).ToList();
break;
}
break;
case OrderByColumnEnum.CaseDate:
switch (OrderBy)
{
case OrderByEnum.ASC:
BuildingList = BuildingList.OrderBy(x => x.CaseDate).ToList();
break;
case OrderByEnum.DESC:
BuildingList = BuildingList.OrderByDescending(x => x.CaseDate).ToList();
break;
}
break;
}
BuildingList.Dump();
}

public class Building
{
public int Pin { get; set; }
public int Age { get; set; }
public DateTime CaseDate { get; set; }

}

/// <summary>
/// 排序欄位
/// </summary>
public enum OrderByColumnEnum
{
/// <summary>
/// 成交日期
/// </summary>
CaseDate,
/// <summary>
/// 建坪
/// </summary>
Pin,
/// <summary>
/// 屋齡
/// </summary>
Age

}

/// <summary>
/// 排序方法
/// </summary>
public enum OrderByEnum
{
ASC = 1,
DESC = 2
}

因為每個欄位不同名稱,又有可能升降冪,所以寫的超級長,如果欄位達到5~6個時,幾乎已經無法維護,但其實只要搭配一點點反射可以把這段改得很漂亮的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//要用來排序的欄位
OrderByColumnEnum OrderByColumn = OrderByColumnEnum.Pin;
//排序的方法
OrderByEnum OrderBy = OrderByEnum.ASC;

//準備資料
var BuildingList = new List<Building>();
for (int i = 0; i < 5; i++)
{
BuildingList.Add(new Building
{
Age = 1 * (i+1),
Pin = 1 * (i+1),
CaseDate = DateTime.Now.AddDays(i +1)
});
}

//排序欄位
var param = OrderByColumnEnum.Pin.ToString();

//透過PropertyInfo操作
var propertyInfo = typeof(Building).GetProperty(param);
switch (OrderBy)
{
case OrderByEnum.ASC:
BuildingList = BuildingList.OrderBy(x => propertyInfo.GetValue(x, null)).ToList();
break;
case OrderByEnum.DESC:
BuildingList = BuildingList.OrderByDescending(x => propertyInfo.GetValue(x, null)).ToList();
break;
}

BuildingList.Dump();

這樣程式是不是變得乾淨許多,但這邊要特別注意的是,因為我的Enum跟Building的屬性剛好都可以對應起來,如果我的Enum名稱與Building的屬性不能對應,那要另外寫對應方式,例如寫到擴充的Enum Attribute,或是用最簡單的Switch Case解決。