承接上篇,我們已完成動態型別建立、屬性存取等基礎設施,現在要實作支援並列排名的擴充方法 Rank。設計上採用委派 Comparison<T> 讓呼叫端自訂比較邏輯,靈活度最高。
方法簽名:
public static IEnumerable<object> Rank<T>(
this IEnumerable<T> value,
Comparison<T> comparison,
string orderName) where T : class
核心邏輯:
List<T> 並依委派排序(預設升序),再 Reverse() 變降序。IEnumerable<object>。public static IEnumerable<object> Rank<T>(this IEnumerable<T> value, Comparison<T> comparsion, string orderName) where T : class
{
string orderColumn = "Rank";
if (!string.IsNullOrEmpty(orderName)) orderColumn = orderName;
List<T> list = value.ToList<T>();
list.Sort(comparsion); // 升序
list.Reverse(); // 降序
List<object> returnlist = new List<object>();
int order = 1;
int pcount = 0;
// 動態建立型別:原屬性 + 排名欄位
Dictionary<string, string> dictionarytype = TypeTransform(typeof(T));
dictionarytype.Add(orderColumn, typeof(int).FullName);
Type type = DynamicCreateType(dictionarytype, new string[] { "System.dll", "System.Core.dll" });
for (int i = 0; i < list.Count; i++)
{
Dictionary<string, object> tempRank = DynamicGetProperty(list[i]);
tempRank.Add(orderColumn, order);
returnlist.Add(DynamicSetProperty(type, tempRank));
if (i < list.Count - 1)
{
int result = comparsion(list[i], list[i + 1]);
if (result != 0)
{
if (pcount == 0) order++;
else { order = order + 1 + pcount; pcount = 0; }
}
else pcount++;
}
}
return returnlist;
}
定義城市薪資類別:
public class CityInfo
{
public string City { get; set; }
public float Salary { get; set; }
}
呼叫 Rank 並繫結至 GridView:
var s = new List<CityInfo> {
new CityInfo(){ City = "上海", Salary=8000f },
new CityInfo() { City = "杭州", Salary=8000f },
new CityInfo() { City = "北京", Salary=6000f },
new CityInfo() { City = "廣州", Salary=6000f },
new CityInfo() { City = "深圳", Salary=4000f },
new CityInfo() { City = "成都", Salary=2000f },
new CityInfo() { City = "武漢", Salary=2000f }
};
this.GridView1.DataSource = s.Rank<CityInfo>((c, c1) => c.Salary.CompareTo(c1.Salary), "位次");
this.GridView1.DataBind();
輸出結果正確處理並列:
| City | Salary | 位次 |
|---|---|---|
| 杭州 | 8000 | 1 |
| 上海 | 8000 | 1 |
| 北京 | 6000 | 3 |
| 廣州 | 6000 | 3 |
| 深圳 | 4000 | 5 |
| 武漢 | 2000 | 6 |
| 成都 | 2000 | 6 |
此擴充方法泛用性強,可套用於任何實作 class 的集合,且排名邏輯符合 SQL RANK() 語意。