使用c#在用户定义的属性上对对象列表进行排序

时间:2013-11-15 10:53:39

标签: c# sorting delegates

我有一个具有18个属性的Object(Called MyReading)。 我将此Object的实例添加到List

例如:

List<MyReading> MyReadingsL = new List<MyReading>();
MyReading O1 = new MyReading();
O1._DateTime = "10";
O1._Value1 = "Hello1";
O1._Value2 = "Hello2";
O1._Value3 = "Hello3";
O1._Value4 = "Hello4";

....etc


MyReadingsL.Add(O1);

我需要按18个属性中的任何一个对读数列表进行排序。 (用户决定哪些) 我知道我必须为列表的Sort()方法编写一个委托,在代码中指定我自己的比较逻辑。

例如。 MyReadingsL.Sort(TheDelegate);

问题是,我不想为每个可以可能排序的属性编写18个代理。 也许一个委托,一个(比较代表)接受(MyReading x,MyReading y)和一个字符串,表示要排序的属性。

这怎么可能?

2 个答案:

答案 0 :(得分:3)

很简单。 Linq已经给你了:

MyReadingsL.OrderBy(r => r._Value1);
MyReadingsL.OrderBy(r => r._Value2);
...
MyReadingsL.OrderBy(r => r._Valuen);
...

如果要定义以相同方式调用的外部函数,则您的签名应如下所示:

public IEnumerable<MyReading> GetSortedList(Func<MyReading, string> property) { }

要从字符串转换为属性,您可以定义静态数据成员。

public static IDictionary<string, Func<MyReading, string>> Properties = 
    typeof(MyReading).GetProperties().ToDictionary(p => prop.Name, p => new Func<MyReading, string>(r => p.GetValue(r)));

这个静态成员为您提供了类中所有属性的字典,由其标识字符串键入,并允许您访问可以执行所需Linq操作的委托。

然后,给定一个标识属性的字符串s,您可以以非常低的成本调用MyReadingsL.OrderBy(Properties[s])

答案 1 :(得分:1)

你可以通过linq实现这一目标。你需要做的是传递你想要排序的字符串/属性,然后使用orderby

一般例子:

// Create 10 objects with 2 properties
var num_and_name_list = 
        from num in Enumerable.Range(1,10)
        select new { val=num, name=(""+num+"oeu")};

// Here i'll sort them by the name property.
var sorted_by_name_list = 
        from some_object in num_and_name_list
        orderby some_object.name descending
        select some_object;

结果将如下所示

enter image description here

所以,你只需要看看你如何/在哪里通过你的财产进行排序。


如果您需要从字符串中获取属性,您可以执行以下操作:

// Create 10 objects with 3 properties
var num_and_name_list =
        from num in Enumerable.Range(1, 10)
        select  new ExtraStringDataPoint ( num, num*2,  ("" + num + "oeu"));

// Hunting your property starts
Type myType = num_and_name_list.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

PropertyInfo order_on_this = null;
foreach (PropertyInfo prop in props)
{
    order_on_this = typeof(ExtraStringDataPoint).GetProperty("Y");
}


// Here i'll sort them by the name property.
var sorted_by_name_list =
        from some_object in num_and_name_list
        orderby order_on_this descending
        select some_object;

我的ExtraStringDataPoint看起来像是:

public class ExtraStringDataPoint : IDataPoint
{
    public ExtraStringDataPoint(double x, double y, string s)
    {
        X = x;
        Y = y;
        Extra = s;
    }
    public double X { get; set; }
    public double Y { get; set; }
    public string Extra { get; set; }

    public override string ToString()
    {
        return X +" , " + Y + " , " + Extra;
    }
}

在您的情况下,您可以将所需的变量作为字符串传递,就像我使用“Y”一样。