Linq sorting object by custom property via reflection

Got a Customer

class Country

that has a property that has a string property Name

. Also Customer

implements IComparable<Country>

like this:

public int CompareTo(Country other)
{
    return string.Compare(this.Name, other.Name);
}

      

Now:

var custList = new List<Customer>{...};

custList.OrderBy(cust => cust.Country).ToList(); //Sorts as charm.

      

And if you try to sort through reflection:

var itemProp = typeof(Customer).GetProperty("Country");

custList = c.Customers.ToList()
    .OrderBy(cust => itemProp.GetValue(cust, null)).ToList(); // Fails

      

Throws an exception "At least one object must implement IComparable"

Please explain why this is happening and how to correctly sort the client by custom property through reflection. Thank.

+3


source to share


2 answers


Since it GetValue

returns Object

, you need to implement a non-generic version IComparable

.



void Main()
{
    var custList = new List<Customer>()
    { 
        new Customer(){ Country = new Country(){ Name = "Sweden" } },
        new Customer(){ Country = new Country(){ Name = "Denmark" } },
    };

    var itemProp = typeof(Customer).GetProperty("Country");

    custList = custList.OrderBy(cust => itemProp.GetValue(cust, null)).ToList();

    custList.Dump();
}

public class Country : IComparable<Country>, IComparable
{
    public string Name {get;set;}

    public int CompareTo(Country other)
    {
        return string.Compare(this.Name, other.Name);
    }

    public int CompareTo(object other)
    {
        var o = other as Country;
        if(o == null)
            return 0; //Or how you want to handle it
        return CompareTo(o);
    }
}

public class Customer
{
    public Country Country{get;set;}
}

      

+3


source


Assuming the base type is correct (i.e. Country

), you should do this while it Country

implements IComparable

:

Here's an example of a console application that works correctly (note that there is no error handling):



using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    class Number: IComparable<Number>, IComparable
    {
        public Number(int value)
        {
            Value = value;
        }

        public readonly int Value;

        public int CompareTo(Number other)
        {
            return Value.CompareTo(other.Value);
        }

        public int CompareTo(object obj)
        {
            return CompareTo((Number) obj);
        }
    }

    class Test
    {
        public Number Number;

        public object Obj
        {
            get { return Number; }
        }

        public override string ToString()
        {
            return Number.Value.ToString();
        }
    }

    internal static class Program
    {
        static void Main()
        {
            var itemProp = typeof(Test).GetProperty("Obj");

            Console.WriteLine(string.Join("\n",
                data().OrderBy(x => itemProp.GetValue(x, null))));
        }

        static IEnumerable<Test> data()
        {
            for (int i = 0; i < 10; ++i)
                yield return new Test {Number = new Number(10-i)};
        }
    }
}

      

+1


source







All Articles