0

I have a method through an ObjectDataSource feeds a gridview and allows sorting by column using lambda expressions:

    public IList<UsersEntity> GetUsers()
    {
        return new List<UsersEntity>(new[] {
            new UsersEntity{ UsrId =1, UsrName="Luis" }, 
            new UsersEntity{ UsrId = 2, UsrName = "Pablo"} });
    }

    public IList<UsersEntity> GetUsers(string OrderBy)
    {
        string[] ordParts = OrderBy.Split(' ');
        string ordBy = ordParts[0];
        string direction = "ASC";
        if (2 == ordParts.Length)
            direction = "DESC";

        //Get Unsorted List
        List<UsersEntity> Lista = (List<UsersEntity>)GetUsers();

        //Function to order 
        Func<UsersEntity, object> myFunct = null;
        myFunct = (usr) => {
            if ("UsrId" == ordBy) return usr.UsrId;
            else return usr.UsrName;
        };

        //sort list
        if ("ASC" == direction)
            return Lista.OrderBy(myFunct).ToList();
        else
            return Lista.OrderByDescending(myFunct).ToList();

    }

But I want something more functional, something that works for all types of lists and does not involve adding a lot of code. So I wrote this function that I can not complete:

public class OrdenarEntidades<T>
{
    public static IEnumerable<T> SortList(IEnumerable<T> Listado, string OrderByArg)
    {
        string[] arrOrderBy = OrderByArg.Split(' ');
        string orderBy = arrOrderBy[0];
        string direction = "ASC";
        if (2 == arrOrderBy.Length)
            direction = "DESC";

        foreach (PropertyInfo pInfo in typeof(T).GetProperties())
        {
            if (orderBy == pInfo.Name)
            {
                Type tipDev = pInfo.PropertyType;
                Func<T, tipDev> MyFunct = (Entity) => { pInfo.GetValue(Entity, null); };

                if ("ASC" == direction)
                    Listado.OrderBy(MyFunct);
                else
                    Listado.OrderBy(MyFunct);
            }
        }

        return Listado;
    }
}

I know this code does not compile, however expresses the idea of what I want to accomplish.

Marc Gravell gives an approximation to what I'm looking for (here), but do not know not how to adapt it to my code

Beforehand, thank you very much.

Community
  • 1
  • 1
Luis E. V.
  • 65
  • 1
  • 7
  • http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet – Luis E. V. Sep 21 '13 at 03:29
  • Thinking more about your question... What is the context you are going to use the function? Seems like a lot of trouble just to wrap linq functionality. Are OrderBy strings stored in the DB? – Maxim Balaganskiy Sep 21 '13 at 04:22

1 Answers1

0

You need something like

public class OrdenarEntidades<T>
{
    public static IOrderedEnumerable<T> SortList(IEnumerable<T> Listado, params Func<T, object>[] orders)
    {
       if(orders.Length == 0)
           return Listado;
       IOrderedEnumerable<T> result = Listado.OrderBy(orders[0]);
       for(int i = 1; i < orders.Length; ++i)
           result = result.ThenBy(orders[i]);
       return result;
    }
}

This supports only ASCENDING order. To allow both directions wrap Func<T, object> in a class with the direction property based on which OrderBy or OrderByDescending is called.

The function can be called like this

var usersSorted = OrdenarEntidades<UserEntity>.SortList(users, user=>user.UsrId, user=>user.UsrName);
Maxim Balaganskiy
  • 1,444
  • 12
  • 23