List.Sort by property name - 包括子类

时间:2016-07-01 06:13:13

标签: c# list sorting reflection

我有点挑战。我需要对一个对象列表进行排序,我需要从表示任何子类中属性路径的字符串中对其进行排序。 我需要使用List.Sort()而不是OrderBy()。

以免举一个简单的例子。我有一个由两个子类代表的人员名单,用于识别和姓名

public class NameParts
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

public class Identification
{
    public String NiNumber { get; set; }
    public NameParts Name { get; set; }
}

public class Person
{
    public String Email { get; set; }
    public String Phone { get; set; }
    public Int16 Age { get; set; }

    public Identification Id { get; set; }
}

现在我需要按年龄对列表进行排序。非常简单

 public static void SortByAge(List<Person> listToSort)
 {
     listToSort.Sort((x, y) => x.Age.CompareTo(y.Age));
 }

即使是NiNumber和FirstName,这种方式也相当简单

 public static void SortByNiNumber(List<Person> listToSort)
 {
      listToSort.Sort((x, y) => x.Id.NiNumber.CompareTo(y.Id.NiNumber));
 }

 public static void SortByFirstName(List<Person> listToSort)
 {
      listToSort.Sort((x, y) => x.Id.Name.FirstName.CompareTo(y.Id.Name.FirstName));
 }

现在是棘手的部分。我需要执行以上所有排序,给出一个字符串,表示要排序的属性的路径。 喜欢&#34; Id.Name.FirstName&#34;

所以我需要

 public static void SortByAny(List<Person> listToSort, String sortBy)
 {
   //??????
 }

可以用

调用
 List<Person> theList = new List<Person>();
 SortByAny(theList, "Age");
 SortByAny(theList, "Id.NiNumber");
 SortByAny(theList, "Id.Name.FirstName");

我知道我需要使用反射,我已经设法这样做了但是我不能比Person类本身的属性更进一步,所以我可能需要做其他的事情,这就是我所在的地方。我被卡住了。

有没有人对如何解决这个问题有一些很好的想法?

由于

3 个答案:

答案 0 :(得分:0)

因为通过反射获取属性非常困难,所以只需使用和修改此代码:

public static void SortByAny(List<Person> listToSort, String sortBy)
{
    if (sortBy == "Email")
        listToSort.Sort((x, y) => x.Email.CompareTo(y.Email));
    else if (sortBy == "Phone")
        listToSort.Sort((x, y) => x.Phone.CompareTo(y.Phone));
    else if (sortBy == "Age")
        listToSort.Sort((x, y) => x.Age.CompareTo(y.Age));
    else if (sortBy == "Id.NiNumber")
        listToSort.Sort((x, y) => x.Id.NiNumber.CompareTo(y.Id.NiNumber));
    else if (sortBy == "Id.Name.FirstName")
        listToSort.Sort((x, y) => x.Id.Name.FirstName.CompareTo(y.Id.Name.FirstName));
    else if (sortBy == "Id.Name.LastName")
        listToSort.Sort((x, y) => x.Id.Name.LastName.CompareTo(y.Id.Name.LastName));
}

答案 1 :(得分:0)

你真的需要把反思放到位吗?如果你需要按照特定和确定数量的“路径”对列表进行排序,我建议你以固定的方式实现它,直接进行排序。也许转换可能会有所帮助?

switch(sortByString){
    case: "Id.NiNumber":
    SortByNiNumber(List<Person> listToSort);
    break;
    ...
}

如果你没有太多的选择,它会更快。也许您可以使用搜索路径和委托或操作字典替换开关。

答案 2 :(得分:0)

您可以修改方法@ E.Mourits链接:C# dynamic. String property path。 我包含了一些错误检查,如果出现错误,您必须检查$(document).ready InnerException方法的InvalidOperationException可以抛出。

Sort

如果您要比较的某些值未实现static void SortByAny<T>(List<T> list, string path) { list.Sort((x, y) => ReflectOnPath(x, path).CompareTo(ReflectOnPath(y, path))); } static IComparable ReflectOnPath(object o, string path) { object value = o; var pathComponents = path.Split('.'); foreach (var component in pathComponents) { if (value == null) { throw new NullReferenceException($"Path '{path}' can not be resolved at: {component}."); } var prop = value.GetType().GetProperty(component); if (prop == null) { throw new ArgumentException($"Path '{path}' can not be resolved at: {component}.", nameof(path)); } value = prop.GetValue(value, null); } if (!(value is IComparable)) { throw new ArgumentException($"Value at path '{path}' does not implement ICompareable.", nameof(path)); } return (IComparable)value; } ,则必须在此情况下添加更多详细信息,以便比较它们。