Mose
Mose

Reputation: 1917

IOrderedEnumerable and defensive programming

I'm fond of defensive programming. I hate exception throwing, but this is not the subject of my question.

I adapted an extension to linQ to be able to perform an order by with a column name

        public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)

With defensive programming, this method returns the given enumerable if the column name is not valid.

Now I need to perform a secondary sorting with ThenBy. So I need that signature :

        public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)

I need to return a IOrderedEnumerable. My problem is to keep my defensive programming feature : I must return the given set is the column name is invalid.

Is there a clean way to do this ? All I'm thinking of are kind of tricks :

And advice / suggestion ? Thanks

Upvotes: 2

Views: 1139

Answers (1)

Roman Boiko
Roman Boiko

Reputation: 3586

You may do any ordering. If column doesn't exist, just leave your input enumerable as it was before. To do this, create key selector that returns the same value for all elements.

See example:

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

static class Program
{
    public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression) where T : class
    {
        Func<T, Int32> keySelector = (elem) =>
        {
            PropertyInfo pi = typeof(T).GetProperty(sortExpression, typeof(Int32));
            if (pi == null)
                return 0; // return the same key for all elements

            return Int32.Parse(pi.GetValue(elem, null).ToString());
        };

        return list.OrderBy(keySelector);
    }

    static void Main(string[] args)
    {
        // Create an array of strings to sort.
        string[] fruits = { "apricot", "orange", "banana", "mango", "apple", "grape", "strawberry" };

        // Sort by "column" Length
        foreach (string s in fruits.OrderBy<string>("Length"))
            Console.WriteLine(s);
        Console.WriteLine();

        // Sort by non-existing column
        foreach (string s in fruits.OrderBy<string>("ength"))
            Console.WriteLine(s);
        Console.ReadKey();
    }
}

Upvotes: 3

Related Questions