Archive for January, 2010

Extension Methods

Extension methods are a handy feature that allows you to extend the functionality of existing classes for which you do not have the source. Extension methods must be static and the type following the ‘this’ keyword indicates the type that is extended by this method.

More information on extension methods can be found here

These are just some of the extension methods I commonly use to make everyday coding a little easier and more readable.

/// <summary>
/// Reformat a string so that the first letter of every word is capitalised and every other letter is lower case
/// </summary>
/// <param name="str">String to format</param>
/// <returns>Formatted string</returns>
public static string ToTitleCase(this string str)
{
    CultureInfo ci = new CultureInfo("en");
    TextInfo cc = ci.TextInfo;
    return cc.ToTitleCase(str);
}
 
/// <summary>
/// Convert this string to its enum type
/// </summary>
/// <typeparam name="T">Type of enum</typeparam>
/// <param name="enumValue">string value to parse</param>
/// <returns>Enum type parsed from string</returns>
public static T ConvertToEnum<T>(this string enumValue) where T : struct
{
     if (!typeof(T).IsEnum) throw new InvalidEnumArgumentException("T must be an enum");
     return (T)Enum.Parse(typeof(T), enumValue, true);
}
 
/// <summary>
/// Get the value of a table column from a reader object
/// </summary>
/// <typeparam name="T">Type  of expected return value</typeparam>
/// <param name="reader">Reader oject to get the value from</param>
/// <param name="columnName">Name of column to retrieve the value from</param>
/// <returns>Column Value</returns>
/// <exception cref="NullReferenceException">If T is not nullable and the column value is null</exception>
public static T GetColumnValue<T>(this IDataReader reader, string columnName)
{
       if (reader.IsDBNull(reader.GetOrdinal(columnName)))
       {
           if (
               (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>))
               || typeof(T) == typeof(string)
              )
           {
               return default(T);
           }
           else throw new NullReferenceException("DB Value is null");
       }
       else return (T)reader[columnName];
 }
 
//The above methods are called like this ...
string myStr ="exAmple sTrinG";
Console.WriteLine(myStr.ToTitleCase()); //Output --> Example String
 
//assume we have the namespace Microsoft.SqlServer.Management.Smo imported
string varChar = "VarChar";
SqlDataType testVrChr = varChar.ConvertToEnum<SqlDataType>();
 
//where reader is an IDataReader
int? value = reader.GetColumnValue<int?>("ColName");

Windows UI Threading

Using background threads to handle long running processes such as fetching data from the db should be common practice when developing windows forms. Failure to do so will result in a clunky UI that will lock up and may appear as crashed to the user. It also allows you to do nice things like updating progress bars etc.

A common trap is trying to call a method which updates a UI control from a background thread. This will result in the “Cross Thread Call” exception which can frighten many developers away from threading in the IU. Here is a pattern I tend to follow when threading UI that takes a lot of the mystery out of things and keeps the UI running smoothly.

First we have a method that calls a long running process. In this method we simply create a new thread in which to run the process and get it started.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Do some long running process on a background thread
/// </summary>
private void Start()
{
     lbl.Text = string.Empty;
     Thread worker = new Thread(DoSomething);
     worker.Start();
}
 
/// <summary>
/// Long running process 
/// </summary>
private void DoSomething()
{
     for (int i = 0; i <= 100; i+=5)
     {
          UpdateProgressBar(i);
          Thread.Sleep(500);   
     }
}

In each iteration of the loop we update the value of a progress bar. This however can only be achieved on the UI thread and this method was called on the background thread. Normally this would throw an exception as the invoke keyword is not used but because of the way the UpdateProgressBar method has been written this is not an issue.

The code below shows how to write any method that updates a UI control so that it can be called safely from any thread and will always execute on the UI thread no matter what the thread the caller is on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// <summary>
/// Something that updates a UI control that 
/// might be called from a background thread 
/// </summary>
/// <param name="progress"></param>
private void UpdateProgressBar(int progress)
{
     //Wrap any code that updates a UI control in this anonymous delegate
     Func<int, object> work = delegate(int progressCount)
     {
        if (progressCount < 0) progressCount = 0;
        if (progressCount > 100) progressCount = 100;
        progressBar1.Value = progressCount;
        if (progressCount == 100) lbl.Text = "Done!";
        return null;
     };
 
     //Check if we are running on a background thread and if so use Invoke
     //otherwise just call the delegate
     if (this.InvokeRequired) Invoke(work, progress);
     else work(progress);
}

The Func is an anonymous delegate … all logic that affects controls should be wrapped in this. The last two lines handle the differing threads. InvokeRequired determines if we are on the UI thread or the background thread. If we are on a background thread it will return true and we call Invoke on the anonymous method to ensure it is executed on the UI thread. If we are already on the UI thread the method is just called without Invoke.

By structuring the control update methods this way they can be called from any thread and will never throw an error due to cross thread calls.

Return top