Sorting Generic Lists With Nested Types Using LINQ

Hi,

It is a feact that generics made many things more simple for .Net developers since it was introduced to the .Net Framework 2.0. But to say the truth is is some hard work to do some jobs over it. For example, for many developers it is confusing to sort a generic list by using the Sort() methods of it. Today as usual :) we will generate a helper class to help us sorting generic lists with nested types using linq.

The brand new SortList function is here;

public static List SortList(List listToBeSorted, string sortBasePropertyName, SortDirection sortDirection)
{
    IOrderedEnumerable result;
    if (!string.IsNullOrEmpty(sortBasePropertyName))
    {
        if (sortDirection == SortDirection.Ascending)
        {
            result = from i in listToBeSorted
                     orderby GetSortBaseProperty(i, sortBasePropertyName)
                     select i;
        }
        else
        {
            result = from i in listToBeSorted
                     orderby GetSortBaseProperty(i, sortBasePropertyName) descending
                     select i;
        }
        return result.ToList();
    }
    else
    {
        return listToBeSorted;
    }
}

The function takes the list, the name of the property and the sort direction according to which the list will be sorted as parameters and then returns the sorted list as result. Now lets talk about how it works. The function does the sorting job with the help of LINQ and because the LINQ returns an object of type IOrderedEnumerable we declared the result object of this type. As you see LINQ is the hero of this function because it does all the things right :) But as they say the first glance may be deceiving. Because the LINQ needs the type of object that is being sorted. In this sample the type of the i is needed to be known. Furthermore, as indicated in the title of this article we want the ability to sort the generic list which may have nested types. Sorting a generic list of employee class according to the name property is a job but sorting that list according to the name property of the department property of employee class is a harder job :)

Now please applause for the hero, GetSortBaseProperty function. I think this function is more complicated than the pretending hero SortList function. Before talking about it here itself.

protected static object GetSortBaseProperty(object o, string SortBasePropertyName)
{
    if (SortBasePropertyName.Contains('.'))
    {
            int dotIndex = SortBasePropertyName.IndexOf(".") + 1;
            object top1Prop = o.GetType().InvokeMember(SortBasePropertyName.Split('.')[0], System.Reflection.BindingFlags.GetProperty, null, o, null);
              return GetSortBaseProperty(top1Prop, SortBasePropertyName.Substring(dotIndex, SortBasePropertyName.Length - dotIndex));
    }
    else
    {
            return o.GetType().InvokeMember(SortBasePropertyName, System.Reflection.BindingFlags.GetProperty, null, o, null);
    }
}

 

First of all the GetSortBaseProperty is a recursive function. Because we have no limit for the nested types. I mean the employee class may have property of type department class and the department class may have a property of type city and we may want to sort the list according to the name of that city :) To say the truth I did not think that much complicated when I wrote this helper class first. But one day my colleague Ahu has come to me and said I want to sort a generic list according to the property of a nested type. Firstly, I resisted for some while but then surrendered when getting the idea of making the GetSortBaseProperty function recursive; I appreciate her for helping to make this magnificent helper class more magnificent :)

Now, the function uses reflection to get the property of the input parameter of object o, as you remember o was the item of the generic list. If the SortBasePropertyName property parameter contains a dot (.) we know that the property is a nested type and then the function calls itself again, this time with a o parameter of inner type of first o parameter and SortBaseProperyName parameter of first SortBaseProperyName by cropping the first part. I think I could not described enough clean. Look at this,

 

  Object o SortBasePropertyName Result
1st round trip class employee Department.Name” department class
2nd round trip class department Name name property

Wait! never mind about the above table I found a better and a more practical sample to describe it more comprehensible. Assume that you have a generic list of employees and the employee class has a property of type department which has a property of string name. Then in your page you databinded a gridview control to the list of employees. To be able to sort the list according to the deaprtment name you should set the SortExpression of the related column to Department.Name :) Here is the aspx code of gridview;

<asp:GridView ID=”grvEmployees” runat=”server” AllowSorting=”True” CellPadding=”4″ AutoGenerateColumns=”false” ForeColor=”#333333″ GridLines=”None” OnSorting=”grvEmployees_Sorting”>

<Columns>

            <asp:BoundField DataField=”Id” SortExpression=”Id” HeaderText=”Id” />

<asp:BoundField DataField=”Name” SortExpression=”Name” HeaderText=”Name” />

<asp:BoundField DataField=”Surname” SortExpression=”Surname” HeaderText=”Surname” />

<asp:BoundField DataField=”Age” SortExpression=”Age” HeaderText=”Age” />

<asp:TemplateField SortExpression=”Department.Name HeaderText=”Department”>

<ItemTemplate>

<%# ((employee)Container.DataItem).Department.Name %>

</ItemTemplate>

</asp:TemplateField>

</Columns>

</asp:GridView>

One Response to “Sorting Generic Lists With Nested Types Using LINQ”

  1. adib4u2000 says:

    Very good article

Leave a Reply

Your email address will not be published. Required fields are marked *


7 − two =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>