This method assigns the value of a specified column in a DataRow
to specified property in an object.
I have 3 conditionals handling exceptions, and I want these conditions to throw exceptions.
The final condition just allows the use of a conversion method if it exists. Is there a better way to test for and throw the exceptions?
public class ColumnToPropertyMap<colType, propType>
{
public string ColumnName { get; private set; }
public string PropertyName { get; private set; }
private Func<colType, propType> conversion;
public virtual void Map<T>(T obj, DataRow row)
{
if (!row.Table.Columns.Contains(this.ColumnName))
{
throw new ArgumentException(
String.Format(@"Column ""{0}"" does not exist in the row.", this.ColumnName));
}
PropertyInfo property = obj.GetType().GetProperty(this.PropertyName);
if (property == null)
{
throw new ArgumentException(String.Format(@"Property ""{0}"" does not exist for object.", this.PropertyName));
}
var value = row.IsNull(this.ColumnName) ? row[this.ColumnName].GetDefaultValue(typeof(colType)) : row[this.ColumnName];
if (conversion == null && property.PropertyType != row.Table.Columns[this.ColumnName].DataType)
{
throw new InvalidCastException(
string.Format(@"Mapping for {0} to {1} failed. Unable to convert {2} to {3}.", this.ColumnName, this.PropertyName, value.GetType(), property.PropertyType));
}
if (conversion != null)
{
value = conversion((colType)value);
}
property.SetValue(obj, value, null);
}
}
Incorporating @Leonid and @SmartLemons comments/answers into consideration, I changed it to this:
public virtual void Map<T>(T obj, DataRow row)
{
PropertyInfo property = obj.GetType().GetProperty(this.PropertyName);
ValidateArguments(property, row);
var value = row.IsNull(this.ColumnName) ? row[this.ColumnName].GetDefaultValue(typeof(colType)) : row[this.ColumnName];
if (conversion != null)
{
value = conversion((colType)value);
}
property.SetValue(obj, value, null);
}
private void ValidateArguments(PropertyInfo property, DataRow row)
{
if (!row.Table.Columns.Contains(this.ColumnName))
{
throw new ArgumentException(
String.Format(@"Column ""{0}"" does not exist in the row.", this.ColumnName));
}
if (property == null)
{
throw new ArgumentException(String.Format(@"Property ""{0}"" does not exist for object.", this.PropertyName));
}
if (conversion == null && property.PropertyType != row.Table.Columns[this.ColumnName].DataType)
{
throw new InvalidCastException(
string.Format(@"Mapping for {0} to {1} failed. Unable to convert {2} to {3}.", this.ColumnName, this.PropertyName, row.Table.Columns[this.ColumnName].DataType.Name, property.PropertyType));
}
}
Takes the argument validation out of the method and makes the intent of the Map
method clearer.
public ColumnToPropertyMap(string columnName, string propertyName){}
) \$\endgroup\$