使用xy排序中的变量

我现在有以下内容:

switch (Mysort) { case "reqDate": lstDMV.Sort((x, y) => DateTime.Compare(x.RequestDate, y.RequestDate)); break; case "notifDate": lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate)); break; case "dueDate": lstDMV.Sort((x, y) => String.Compare(x.TargetDateShort, y.TargetDateShort)); break; case "days": lstDMV.Sort((x, y) => x.DaysLapsed.CompareTo(y.DaysLapsed)); break; } 

我想摆脱案例陈述,只做以下事情:

 lstDMV.Sort((x, y) => String.Compare(x.MySort, y.MySort)); 

案例陈述是巨大的,它将真正削减可读性。 但是因为MySort不包含在lstDMV所以它不起作用。 还有其他方法可以替代它吗?

我当然会更改文本以确保MySort变量值与lstDMV属性名称完全匹配。

我也试过以下没有运气:(

  if (sort != "") { string xsort, ysort; xsort = "x." + sort; ysort = "y." + sort; lstDMV.Sort((x, y) => String.Compare(xsort, ysort)); } 

比较器Func的字典

  public class YourDataClass { public string RequestDate { get; set; } public string NotifDate { get; set; } . . . } public class Sorter where T : YourDataClass { private Dictionary> actions = new Dictionary> { {"reqDate", (x, y) => String.Compare(x.RequestDate, y.RequestDate)}, {"notifDate", (x, y) => String.Compare(x.NotifDate, y.NotifDate)} }; public IEnumerable Sort(IEnumerable list, string howTo) { var items = list.ToArray(); Array.Sort(items, (x, y) => actions[howTo](x, y)); return items; } } public void Sample() { var list = new List(); var sorter = new Sorter(); var sortedItems = sorter.Sort(list, "reqDate"); } 

那么你可以使用reflection,假设你的所有属性类型都实现了IComparable

 private class Test { public DateTime RequestDate { get; set; } public string Name { get; set; } } private static void Main(string[] args) { var list = new List { new Test { RequestDate = new DateTime(2012, 1, 1), Name = "test" }, new Test { RequestDate = new DateTime(2013, 1, 1), Name = "a_test" }, }; string mySort = "RequestDate"; list.Sort((x, y) => { // Gets the property that match the name of the variable var prop = typeof(Test).GetProperty(mySort); var leftVal = (IComparable)prop.GetValue(x, null); var rightVal = (IComparable)prop.GetValue(y, null); return leftVal.CompareTo(rightVal); }); Console.Read(); } 

我不建议这样做,因为即使代码可能较少,它的可读性也低于您目前使用的switch

Linq和Reflection的组合,通过3行代码解决您的问题。 这是概念certificate:

 public class Test { public string Name; public int Age; public DateTime Since; } void Main() { var tests = new Test[] { new Test(){Name="Dude", Age=23, Since = new DateTime(2000,2,3)}, new Test(){Name="Guy", Age=29, Since = new DateTime(1999,3,4)}, new Test(){Name="Man", Age=34, Since = new DateTime(2008,11,5)}, new Test(){Name="Gentleman", Age=40, Since = new DateTime(2006,7,6)} }; //up until here, all code was just test preparation. //Here's the actual problem solving: string fieldToOrderBy = "Since"; //just replace this to change order FieldInfo myf = typeof(Test).GetField(fieldToOrderBy); tests.OrderBy(t=>myf.GetValue(t)).Dump(); //the Dump() is because I ran this in LinqPad. //Replace it by your favaorite way of inspecting an IEnumerable } 

请注意,在排序之前获取字段信息,以尝试提高性能。

我知道你的“SortBy”字符串不是字段名称,但这是问题的简单部分,你可以通过使用字典将SortBy字符串映射到FieldName来解决。

假设您的xyA类型,您可以将映射存储在字典中:

 var sortingFuncs = new Dictionary>(); 

然后,调用排序方法将不再需要switch

 lstDMV.Sort(sortingFuncs[Mysort]); 

但请注意,您最终会在其他地方使用相同数量的代码,因为字典必须在某个时刻填充。 一个优点是这个过程可能更加动态,例如,您可以让插件添加自己的排序键以及比较function。

另一方面, 可能会有非常轻微的性能损失,因为编译器不可能再根据符合Mysort值来优化选择代码。

创建属性选择器:

 Func CreatePropSelector(string propertyName) { var parameter = Expression.Parameter(typeof(T)); var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(object)); return Expression.Lambda>(body, parameter).Compile(); } 

并使用它按属性名称排序顺序:

 lstDMV.OrderBy(CreatePropSelector(Mysort)) 

与其他Linq方法一样,它不会对列表进行排序,但会创建枚举器:

 Mysort = "RequestDate"; foreach(var item in lstDMV.OrderBy(CreatePropSelector(Mysort))) // sequence ordered by RequestDate property