Monday, December 19, 2011

C# extension method - OrderBy sort expression as string

Recently I came across a question in a forum where a part of the solution requires the sort expression as string type for the OrderBy extension method. The requirement is, upon passing a string of property name separated by comma, the respective sort need to be applied and returned.

Without explaining further, directly I dive into the implementation so that you can easily infer from that. I altered the snippet got from http://www.extensionmethod.net/Details.aspx?ID=124 based on our needs.

Snippet 1 (Core extension method for OrderBy and ThenBy)

public static class IEnumerableExtensions
{
    public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
    {
        sortExpression += "";
        string[] parts = sortExpression.Split(' ');
        bool descending = false;
        string property = "";

        if (!(parts.Length > 0 && parts[0] != ""))
        {
            throw new Exception("Invalid sort expression.");
        }

        property = parts[0];

        if (parts.Length > 1)
        {
            descending = parts[1].ToLower().Contains("esc");
        }

        PropertyInfo prop = typeof(T).GetProperty(property);

        if (prop == null)
        {
            throw new Exception("No property '" + property + "' in + " + typeof(T).Name + "'");
        }

        if (descending)
            return list.OrderByDescending(x => prop.GetValue(x, null));
        else
            return list.OrderBy(x => prop.GetValue(x, null));
    }

    public static IOrderedEnumerable<T> ThenBy<T>(this IOrderedEnumerable<T> list, string sortExpression)
    {
        sortExpression += "";
        string[] parts = sortExpression.Split(' ');
        bool descending = false;
        string property = "";

        if (!(parts.Length > 0 && parts[0] != ""))
        {
            throw new Exception("Invalid sort expression.");
        }

        property = parts[0];

        if (parts.Length > 1)
        {
            descending = parts[1].ToLower().Contains("esc");
        }

        PropertyInfo prop = typeof(T).GetProperty(property);

        if (prop == null)
        {
            throw new Exception("No property '" + property + "' in + " + typeof(T).Name + "'");
        }

        if (descending)
            return list.ThenByDescending(x => prop.GetValue(x, null));
        else
            return list.ThenBy(x => prop.GetValue(x, null));
    }

    public static IEnumerable<T> OrderByStringExpression<T>(this IEnumerable<T> queryObj, string orderByProperties)
    {
        if (string.IsNullOrWhiteSpace(orderByProperties))
        {
            //throw new Exception("Invalid sort expression");
            return queryObj;
        }

        string[] orderByPropertyArray = orderByProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        IOrderedEnumerable<T> orderedItem = null;

        if (orderByPropertyArray.Length > 0)
        {
            orderedItem = queryObj.OrderBy(orderByPropertyArray[0]);

            if (orderByPropertyArray.Length > 1)
            {
                for (int i = 1; i < orderByPropertyArray.Length; i++)
                {
                    orderedItem = orderedItem.ThenBy(orderByPropertyArray[i]);
                }

            }
        }

        return orderedItem;
    }
}

Snippet 2 (Example code)

var sortResult = listInst.OrderByStringExpression("Id,Name desc");

As you see, each property name should be separated by comma and if required you can specify the sort mode (asc/desc) followed by a blank space with the respective parameter.

Now with the above specified method, we can pass simple comma separated string as sort expression and get the related instance sorted. This will helpful in scenarios like implementing the Repository pattern as I did here.  Hope this helps.

References
http://www.extensionmethod.net/Details.aspx?ID=124





No comments:

Post a Comment

Creative Commons License
This work by Tito is licensed under a Creative Commons Attribution 3.0 Unported License.