in

ASP.NET Weblogs

This Blog

Syndication

ShowUsYour<Blog>

Irregular expressions regularly

Using generics to build generic data logic layers

Consider exposing raw Generic collections from your data logic layers, such as:

   public class PersonManager {
        ...
        public List<Person> ListPeople(...) { ... } ;
   }

When I started messing around with building applications in 2.0 I quickly wrapped Generic collections like so:

  public class PersonCollection : List<Person> {
     ... 
  }

This was normally done so that I could hang a Sort method off of them:

  public class PersonCollection : List<Person>, IBidirectionalSort {
     ... 
     public void Sort( string sortExpression, bool isAscending ) { ... }
  } 

The downside of this approach is that you end up writing fiddly code around calls to generic helper methods.

As an example, let's say that I write a nice generic helper method to page my collections:

    public static void Page(ref List<T> data, int maximumRows, int startRowIndex) 
        where T : IDataObject, new() {

        if (data.Count > 0) {
            if (maximumRows > 0 && startRowIndex >= 0) {
                List<T> tmpColl = null;

                int remainingRowCount = data.Count - startRowIndex;
                int count = (remainingRowCount >= maximumRows) ? maximumRows : remainingRowCount;

                if (count > 0) {
                    tmpColl = new List<T>();
                    tmpColl.AddRange(data.GetRange(startRowIndex, count));
                }
                data = tmpColl;
            }
        }
    }

If I’ve wrapped my collection – as per the PersonCollection example – then using the generic Page method will require temporary object creation when I’m calling it, something like:

   public PersonCollection ListPeople(...) { 
       ...
       PersonCollection people = FillList( reader ) ;
       List<Person> tmp = Page( people, 20, 0 ) ;
       PersonCollection peopleToReturn = new PersonCollection() ;
       peopleToReturn.AddRange( tmp ) ;
       return peopleToReturn ;
   }

So, you can see that by the time we have many generic methods, working with temporary objects becomes cumbersome.  Exposing List<Person> from this method would lead you to build your surrounding methods – such as FillList and Page – to work with your code better but will also lead to leaner code:

    public List<Person> ListPeople(...) { 
       ...
       List<Person> people = FillList<Person>( reader ) ;
       return Page<Person>( people, 20, 0 ) ;
    }

 

Published Mar 29 2005, 07:12 PM by digory
Filed under: ,

Comments

 

Oliver Sturm said:

And to get back to the original idea of the Sort method, why wouldn't you instead create a

class SortedList<T>: List<T> {
public void Sort( ... );
}

that would handle the sorting in a generic way? There are nice helpers for such things in .net 2, like IComparer<T> and Comparison<T>, which make it easy to implement this very flexibly.

And yet another thing: it might be useful to know about PowerCollections (http://www.wintellect.com/powercollections/) if one is interested in this kind of stuff, not only because they have a lot of readily usable code but also because they contain the source code that shows how extensions to collection classes can be implemented.
March 29, 2005 5:55 AM
 

Laurent Kempé said:

Hi Daren,

I see that we are working on the same idea :)
DataAccessLayer.FindAll(PublishedBy(Author)) : http://weblogs.asp.net/lkempe/archive/2005/03/09/391247.aspx

Refactoring the set of Predicate with an Interpreter : http://weblogs.asp.net/lkempe/archive/2005/03/12/394323.aspx

As Oliver is saying you might look at powercollections, it looks good.

Regards
March 29, 2005 4:22 PM

Leave a Comment

(required)  
(optional)
(required)  
Add