views:

24

answers:

2

I have a simple IEnumerable collection of Order objects. I want to write a generic sort function that accepts the collection and a sortkey that corresponds to a property on an Order object. I don't want to hardcode the sort instructions for every property. How can I build a dynamic LINQ string that automatically generates the LINQ for me? Here is my SortOrders() function in its current state:

public IEnumerable<Order> SortOrders(IEnumerable<Order> orders, string sortKey)
        {
            // Sort order records
            try
            {
                IEnumerable<Order> sortedOrders = new List<Order>();

                // Extract sort key and direction from combined sortKey input
                string _sortKey = this.SortKey.Replace(" ASC", "").Replace(" DESC", "");
                bool sortASC = this.SortKey.EndsWith(" ASC");

                switch (_sortKey)
                {
                    case "CustomerID":
                        sortedOrders = (sortASC) ? orders.OrderBy(o => o.CustomerID) : orders.OrderByDescending(o => o.CustomerID);
                        break;
                    case "CustomerAddress":
                        sortedOrders = (sortASC) ? orders.OrderBy(o => o.CustomerAddress) : orders.OrderByDescending(o => o.CustomerAddress);
                        break;
                    case "CustomerCity":
                        sortedOrders = (sortASC) ? orders.OrderBy(o => o.CustomerCity) : orders.OrderByDescending(o => o.CustomerCity);
                        break;
                    default:
                        sortedOrders = orders;
                        break;
                }
                return sortedOrders;
            }
            catch
            {
                return orders; // return original orders list in the event of errors
            }
        }

I am looking to replace all of the case sections like this:

case "CustomerID":
                        sortedOrders = (sortASC) ? orders.OrderBy(o => o.CustomerID) : orders.OrderByDescending(o => o.CustomerID);

with a single directive like this:

sortedOrders = (sortASC) ? orders.OrderBy(o => o.PropertyName) : orders.OrderByDescending(o => o.PropertyName);
+1  A: 

You can pass the expression you want to sort in as a Lamba (this is simplified/pseudocode)

SortOrders(IEnumerable<Order> orders, Func<Order, string> func)
{
    sortedOrders = orders.OrderBy(func) 
    ....                
}


// call:
SortOrders(orders,  o => o.CustomerID);
jdv
This gets me halfway there... How do I generate the function call itself dynamically? In other words, if the Order object has N properties I want to be able to assemble the "o => o.OrderPropertyName" portion dynamically. I don't want to have to hardcode o => o.CustomerID. Thank you for your interest in this question.
Mark
OK. If you want it fully dynamic, look at the other answer. Do realize you don't need to 'hardcode' the lambda you use to sort on. You can pass it around like any variable.
jdv
A: 

You can use Dynamic LINQ and there's no need for the extension method. Just use the extension in the DynamicQueryable class and specify both the key and direction as a string.

var sorted = orders.OrderBy( "CustomerID desc" );
tvanfosson