我在这里遇到了一个情况,我不确定最好的处理方式是什么......
我的前端代码(ASP.NET)不断获取用于填充UI组件的业务对象列表。最近,我实现了一个自然排序,我想用于所有类型的这些列表。 (目前只是对字符串列表进行排序) 根据业务对象的类型,我需要对不同的字段名称进行排序。该字段始终包含字符串。我在编译时知道字段名称。除了Object之外,业务对象没有共同的父级。
我想有一个方法可以为任何类型的Enumerable执行此操作。我无法更改底层业务对象的代码。你会怎么做?
答案 0 :(得分:5)
类似于Linq's orderby?
你必须在IComparer中实现自然排序,但是你只需要使用:
Items.OrderBy(i => i.SomeStringField, NaturalSorter);
答案 1 :(得分:1)
你可以使用反射:
private string GetStringValue(object input, string propertyName)
{
PropertyInfo pi = typeof(input).GetProperty(propertyName);
return pi.GetGetMethod().Invoke(input) as String;
}
这将获取对象的给定属性的值,然后您可以根据此应用排序。
答案 2 :(得分:1)
您需要创建一个键选择器。 Take a look at Enumerable.OrderBy。它的第二个参数是键选择器。实现它以考虑业务对象的类型,例如:
delegate (object o)
{
if (o is BizType1) return ((BizType1)o).Property1;
else if (o is BizType2) return ((BizType2)o).Property2;
}
答案 3 :(得分:1)
由于您没有可以强类型方式访问属性的常用类型,因此您无法直接使用其他答案中建议的OrderBy
。
您需要使用反射来获取对property object的引用,并要求它检索序列中每个项目的值:
public static IOrderedEnumerable<TSource> OrderByProperty<TSource>(
this IEnumerable<TSource> source,
string propertyName)
{
var property = typeof(TSource).GetProperty(propertyName);
return source.OrderBy(item => (string) property.GetValue(item, null));
}
当然,如果在运行时您知道字段和要排序的列表的确切类型,则应使用OrderBy
的强类型重载。此建议仅在您不知道要排序的列表中的项目类型时(即IEnumerable<object>
)。
答案 4 :(得分:1)
您可以使用anonymous function来检索正确的字符串。这意味着您将传递对象列表和lambda表达式或匿名方法委托以将字符串提取到排序方法。
sort(listOfFoos, o => ((Foo) o).name());
我最近自己并没有使用太多的C#,所以如果不起作用,其他人可能会大喊大叫。
答案 5 :(得分:0)
对于每个业务对象,实现IComparable<T>
接口
然后使用LINQ OrderBy
方法,它将自动使用您的方法进行排序。
如果您不想或不想在业务对象类中包含排序逻辑,您也可以实现IComparer<T>
并将其传递给OrderBy
overload。
答案 6 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//lets say this is the list that you have you mah have more fields
List<Person> people = new List<Person>();
people.Add(new Person(25, "Jhon"));
people.Add(new Person(22, "Antonio"));
people.Add(new Person(21, "Waid"));
people.Add(new Person(21, "Chris"));
people.Add(new Person(26, "Lacy"));
people.Add(new Person(21, "Albert"));
people.Add(new Person(45, "Tom"));
people.Add(new Person(65, "Bob"));
var query = from a in people // crate a query from your list in this case the list is people
where a.age > 18 && a.age < 50 // select just people that has an age greater than 0 and less than 100
// maybe you want to filter some results if you dont then delete this line.
orderby a.name // order the results by their name
select a.name; // then select just the name. if you type select just a then query will
// contain a list of ages too.
// loop though the results to see if they were ordered
foreach (string name in query)
{
Console.WriteLine(name);
}
Console.Read();
}
}
// I created this class because I dont know what your list contains I know it has a string therefore I added a string
// you may add more properties and it will still work...
class Person
{
public int age;
public string name;
public Person(int a, string n)
{
age = a;
name = n;
}
}
}