我有点挑战。我需要对一个对象列表进行排序,我需要从表示任何子类中属性路径的字符串中对其进行排序。 我需要使用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类本身的属性更进一步,所以我可能需要做其他的事情,这就是我所在的地方。我被卡住了。
有没有人对如何解决这个问题有一些很好的想法?
由于
答案 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;
}
,则必须在此情况下添加更多详细信息,以便比较它们。