Home > .net 3.0, .net 3.5, c#, Visual Studio 2008 > ConvertTo Extension Method

ConvertTo Extension Method

April 15, 2008

I’ve been revamping an OLD (read: legacy ASP and HTML) project to add in some .NET reporting functionality.  Unfortunately, rewriting the entire application isn’t slated for another year (though I’m working on the architecture changes as I do the reporting to ensure as little rework as possible later on).

The system backs into an old Oracle database that freaks out NHibernate and makes me long for the days of LINQ.  The most challenging part of recreating a DAL from scratch is ensuring that the data you’re using matches the strongly typed objects you’re populating. 

In Oracle’s case, NUMBERs become int32s, NUMBERs become booleans (where approprate), VARCHARs into strings, and so on.  (Oracle not having a boolean type continues to drive me insane).

So, in most cases, the DAL code that populates objects looks something similar to this:

Id = row[“section_id”] != DBNull.Value

       ? Convert.ToInt32(row[“section_id”])

       : 0;

Even the shorthand for the if/else is three lines.  Booleans are even more mindnumbing because they’re stored as numbers and, in my experience, I can’t convert from a number to an int32 to a boolean—all in one line.  So, the code looks like:

if (row[“child”] != DBNull.Value)

{

int childSections = Convert.ToInt32(row[“child”].ToString().Trim());

       section.HasChildren = Convert.ToBoolean(childSections);

}

With a few dozen columns and some very complex dependencies around multiple databases, those extra lines are tedious to both read and write.

What would help? SQL Server 2005 and LINQ, you say?  I agree, but not this time.  A quick method to handle the conversions would be great and since we’re looking at .NET 3.5, perhaps even an extension method.

public static T ConvertTo<T>(this object value) where T : IConvertible

{

return (T)Convert.ChangeType(value, typeof(T));

}

The first iteration works like a champ in most all situations.  Because we’re using a generic constraint of IConvertible, we don’t have to worry about passing classes or types that do not support conversion.

Now, my multiple lines of code for conversion look like:

Id = row[“question_id”].ConvertTo<int>(),

Text = row[“question_displaylabel”].ConvertTo<string>(),

Much better, much cleaner—and easier for someone new to the code to read and understand what’s going on.

Unfortunately, there’s a mishap with that original code.  At least from Oracle (where I’ve done my testing), it cannot convert the NCHAR fields properly to a boolean.  First, I must convert it to an integer, then a boolean (just as I had to do before).   Thankfully, with the extension method, I can write that code once and reuse it throughout the project.

The final (for now) version of the extension method is:

public static T ConvertTo<T>(this object value) where T : IConvertible

{

if (typeof(T) == typeof(bool))

                     return (T) Convert.ChangeType(

Convert.ToInt32(value), typeof (T));

             

return (T)Convert.ChangeType(value, typeof(T));

}

UPDATE: Final doesn’t last very long when you’re dinking.  The DBNull error caught me off guard as the unit tests ran (thank goodness for those).  If DBNull occured, I wanted to simply return the default value of the type specified.  For a string, “”, for an int, 0, etc.

Thankfully, the default keyword is there to help!  The new method checks for DBNull and, if found, returns the default value for the specified type.

public static T ConvertTo<T>(this object value) where T : IConvertible

{

if (value == DBNull.Value)

                     return default(T);

 

if (typeof(T) == typeof(bool))

                     return (T)Convert.ChangeType(

Convert.ToInt32(value), typeof(T));

 

return (T)Convert.ChangeType(value, typeof(T));

}

Now, those pesky nulls in Oracle won’t catch us up.

  1. April 19, 2008 at 11:16 am

    Slick extension method dude.

  2. April 19, 2008 at 1:35 pm

    Thanks; it’s working out really well. I replaced several return methods in one of our primary framework libraries at work and the performance is pretty darned nice. It also reads a LOT better.

    I’m sure I’ll find another snafu, like the DBNull, eventually, but it’s a good work in progress.

  1. No trackbacks yet.
Comments are closed.
%d bloggers like this: