Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Desktop Developer

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

Search

XML Feeds

Google Ads

« Use solution foldersMicrosoft Source Analysis for C# Announced »
comments
Rate Post:
submit to reddit Digg!FacebookDotnetkicks

Since this is probably the most-often reused piece of code I’ve written recently, I thought it may be worth sharing. It is pretty raw still, so I will post it to the wiki as well, and hopefully people will see ways to improve it (and show us!). Here is the link to the wiki page: Generic List Provider in C#.

I wrote this because I found myself constantly writing code to fill lists of objects from database commands. I was too far into the project and the project was a little to small to justify moving to an ORM like NHibernate, but I thought there must be a better way to do this.

It turns out we can do it, using a couple of my favorite features in .NET 2.0, Reflection and Generics. By making this ListProvider a generic class, we can return a list of objects of any type. And by using reflection we can interrogate the type we are working with at runtime, and assign its’ properties.

There is one pretty major limitation of this method, and that is that your property names need to match the column names that you return from the database. When limiting access to the database to stored procs, this is pretty easy to enforce, so I have not needed to find a way around it. I’m sure there is a way to do this by adding a list of database field names and their associated properties that the calling code can provide, but I have not needed to do it yet. Hopefully someone will add to the wiki page and do it for me :D

Anyways here is the code, it is pretty self explanatory:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Reflection;
  5. using System.Data;
  6.  
  7. namespace MyApp.Utilities
  8. {
  9.     public class ListProvider<T> where T: new()
  10.     {
  11.         public List<T> FindAll(IDbCommand com, IDbConnection con)
  12.         {
  13.             //ensure that command object’s connection is set, open connection
  14.             com.Connection = con;
  15.             con.Open();
  16.  
  17.             //create data reader used in filling objects
  18.             IDataReader rdr = com.ExecuteReader();
  19.  
  20.             //instantiate new list of <T> that will be returned
  21.             List<T> returnList = new List<T>();
  22.  
  23.             //need a Type and PropertyInfo object to set properties via reflection
  24.             Type tType = new T().GetType();
  25.             PropertyInfo pInfo;
  26.  
  27.             //x will hold the instance of <T> until it is added to the list
  28.             T x;
  29.  
  30.             //use reader to populate list of objects
  31.             while (rdr.Read())
  32.             {
  33.                 x = new T();
  34.  
  35.                 //set property values
  36.                 //for this to work, command’s column names must match property names in object <T>
  37.                 for (int i = 0; i<rdr.FieldCount; i++)
  38.                 {
  39.                     pInfo = tType.GetProperty(rdr.GetName(i));
  40.                     pInfo.SetValue(x, rdr[i], null);
  41.                 }
  42.  
  43.                 //once instance of <T> is populated, add to list
  44.                 returnList.Add(x);
  45.             }
  46.  
  47.  
  48.             //clean up – assumes you don’t need command anymore
  49.             con.Close();
  50.             com.Dispose();
  51.             rdr.Dispose();
  52.  
  53.             return returnList;
  54.         }
  55.     }
  56. }

I tried to remove most of the comments that didn’t add much (parameter descriptions and what not) but I think its’ still pretty easy to understand. As I said this is a work in progress (I just need to run into a reason to actually need the progress ;) ) so don’t be too rough on me. And feel free to do my job for me offer suggestions to make this better!

About the Author

Alex is a .net and SQL Server developer from southeastern PA, where he lives with a lovely fiance and a veritable smorgasbord of pets. He's also working on a masters degree in Software Engineering. He loves mountain biking, home brewing, and the mono runtime.
Social SitingsTwitterHomePageLTD RSS Feed
1519 views
c#
submit to reddit Digg!FacebookDotnetkicks

Comments and Feedback

1 comment

Comment from: Jim [Visitor]
*****
Took you example and modified it to use attributes instead of the property names. this way your property names don't have to look like your datacolumn names from the database.

Great work.
09/25/09 @ 11:38

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)