Since C# 3.0 it’s possible to write extension methods, these are very useful if you want to extend existing classes but don’t have access to them or if you simply want to add some convenience methods. The latter is what I did here.
If you want to know more about extension methods, you should take a look at this
Action Extensions
I really like the generic Action, Action<T> but i don’t to check for null every single time I want to fire them:
public static class ActionExtensions
{
public static void Fire(this Action action)
{
if (action != null)
{
action();
}
}
public static void Fire<T>(this Action<T> action, T arg)
{
if (action != null)
{
action(arg);
}
}
public static void Fire<T, T2>(this Action<T, T2> action,
T arg1, T2 arg2)
{
if (action != null)
{
action(arg1, arg2);
}
}
}
The same can be done with Func<T, TResult>:
public static TResult Fire<TResult>(this Func<TResult> func)
{
return func != null ? func() : default(TResult);
}
public static TResult Fire<TResult, T>(this Func<T, TResult> func, T arg)
{
return func != null ? func(arg) : default(TResult);
}
DataRow/ IDataRecord Extensions
If you have to work with IDataReaders or DataRows, chances are high that some of your code looks like this:
public void DoSomething(DataTable table)
{
foreach (DataRow row in table.Rows)
{
var customer = new Customer
{
Id = (Guid)row["Id"],
FirstName = row["FirstName"] == DBNull.Value
? string.Empty
: (string)row["FirstName"],
CompanyName = row["CompanyName"] == DBNull.Value
? null
: (string)row["CompanyName"]
};
}
}
public void DoOtherThings(Customer customer, DataRow row)
{
row["Id"] = customer.Id;
row["FirstName"] = customer.FirstName == null
? string.Empty
: customer.FirstName;
row["CompanyName"] = customer.CompanyName == null
|| customer.CompanyName == string.Empty
? DBNull.Value
: customer.CompanyName;
}
These extension methods will reduce the code duplication and make it a little more readable:
public static class DataRecordExtensions
{
public static T GetValue<T>(this IDataRecord dataRecord, string column)
{
return GetValue<T>(dataRecord, column, true);
}
public static T GetValue<T>(this IDataRecord dataRecord, string column,
bool nullString)
{
var value = dataRecord[column];
if (value == DBNull.Value)
{
if (typeof(T) == typeof(string))
{
if (!nullString)
{
return (T) (object) string.Empty;
}
}
return default(T);
}
return (T)value;
}
public static T GetValue<T>(this DataRow row, string column)
{
return GetValue<T>(row, column, true);
}
public static T GetValue<T>(this DataRow row, string column,
bool nullString)
{
var value = row[column];
if (value == DBNull.Value)
{
if (typeof(T) == typeof(string))
{
if (!nullString)
{
return (T)(object)string.Empty;
}
}
return default(T);
}
return (T)value;
}
public static void SetValue<T>(this DataRow row, T value,
string column)
{
SetValue(row, value, column, false);
}
public static void SetValue<T>(this DataRow row, T value,
string column, bool defaultDbNull)
{
object val = value;
if (defaultDbNull)
{
if (ReferenceEquals(value, default(T)))
{
val = DBNull.Value;
}
else if (typeof(T) == typeof(string))
{
if ((string)(object)value == string.Empty)
{
val = DBNull.Value;
}
}
}
else if(val == null)
{
if (typeof(T) == typeof(string))
{
val = string.Empty;
}
else
{
val = DBNull.Value;
}
}
row[column] = val;
}
}
The code above could now be written as:
public void DoSomeThing(DataTable table)
{
foreach (DataRow row in table.Rows)
{
var customer = new Customer
{
Id = row.GetValue<Guid>("Id"),
FirstName = row.GetValue<string>("FirstName"),
CompanyName = row.GetValue<string>("CompanyName", true)
};
}
}
public void DoOtherThings(Customer customer, DataRow row)
{
row.SetValue(customer.Id, "Id");
row.SetValue(customer.FirstName, "FirstName");
row.SetValue(customer.CompanyName, "CompanyName", true);
}