views:

148

answers:

2

I implemented an extension "MyExtensionSortMethod" to sort collections (IEnumerate). This allows me to replace code such as 'entities.OrderBy( ... ).ThenByDescending( ...)' by 'entities.MyExtensionSortMethod()' (no parameter as well).

Here is a sample of implementation:

//test function
function Test(IEnumerable<ClassA> entitiesA,IEnumerable<ClassB> entitiesB ) {
   //Sort entitiesA , based on ClassA MySort method
   var aSorted = entitiesA.MyExtensionSortMethod(); 

   //Sort entitiesB , based on ClassB MySort method
   var bSorted = entitiesB.MyExtensionSortMethod(); 
}

//Class A definition
public classA: IMySort<classA> {
  ....

  public IEnumerable<classA> MySort(IEnumerable<classA> entities)
  {
      return entities.OrderBy( ... ).ThenBy( ...);  
  }
}

public classB: IMySort<classB> {
  ....

  public IEnumerable<classB> MySort(IEnumerable<classB> entities)
  {
      return entities.OrderByDescending( ... ).ThenBy( ...).ThenBy( ... );  
  }
}

//extension method
public static IEnumerable<T> MyExtensionSortMethod<T>(this IEnumerable<T> e) where T : IMySort<T>, new()
{
    //the extension should call MySort of T
    Type t = typeof(T);
    var methodInfo = t.GetMethod("MySort");

    //invoke MySort 
    var result = methodInfo.Invoke(new T(), new object[] {e});

    //Return 
    return (IEnumerable < T >)result;
}

public interface IMySort<TEntity> where TEntity : class
{
    IEnumerable<TEntity> MySort(IEnumerable<TEntity> entities);
}

However, it seems a bit complicated compared to what it does so I was wondering if they were another way of doing it?

A: 

Why don't you use a Predicate for this? It would allow you to pass your sorting conditions as a delegate.

The example below doesn't sort, but it should serve as a decent example of the technique:

 private class Book   
   {   
       public string Author { get; set; }   
       public string Name { get; set; }   
       public DateTime Published { get; set; }   
   }   

   //Create and fill a list of books   
   private List<Book> Books = new List<Book> {   
        new Book { Author="Mcconnell",Name="Code Complete", Published=new DateTime(1993,05,14) },  
        new Book { Author="Sussman",Name="SICP (2nd)", Published=new DateTime(1996,06,01) },  
        new Book { Author="Hunt",Name="Pragmatic Programmer", Published=new DateTime(1999,10,30) },  
    };  

    // returns a new collection of books containing just SICP and Pragmatic Programmer.  
    private IEnumerable<Book> BooksPublishedAfter1995()  
    {  
        return Books.FindAll(Book => Book.Published > new DateTime(1995, 12, 31));
    }

http://www.rvenables.com/tag/predicates/

Then again, now we're back to OrderBy, aren't we?

Robert Harvey
Could you be more specific? With a small sample? Thank you.
I wasn't prepared to assemble the whole thing. I'm still trying to figure out why you dropped something as elegant as OrderBy for your example. However, I'll give it a shot. See my edit.
Robert Harvey
In the entire project we mainly have to work with many collections. They can be updated any time and they may require to be sorted based on a graph. For instance to grab the last() entity you can end up with something like:entities.OrderBy(e=>e.Parent.Parent.Parent.Something).ThenBy(e=>e.Parent.Parent.Something)... .ThenBy(e=>e.Something).Last()This is fine except if it happens often. It can also be hard to maintain. DataLoadOptions could be a solution but it doesn't fit our case. So I would prefer to have something like entities.SortMe().Last() where SortMe is define once only.
Xavier, see my new posted answer.
Robert Harvey
A: 

If you want to specify a custom sort for your objects, you can implement the IComparable interface on your class. See the following article that explains how to do it:

Implementing IComparable for Sorting Custom Objects
http://codebetter.com/blogs/david.hayden/archive/2005/02/27/56099.aspx

Robert Harvey