On the first part I described Value Injecter and how to use it in a object-to-object mapping. In this second part I’ll show a complete sample of how to map an object using the property names and converting the property types from the source to the target type.
using System;
using System.ComponentModel;
using Omu.ValueInjecter;
namespace Infrastructure.Mappers
{
/// <summary>
/// The custom loop value injector class will map all properties with the same name, even if the type is not the same.
/// When the source and target types are not the same, a conversion will be attempted by a converter dynamically created.
/// </summary>
public class NameValueInjection : CustomizableValueInjection
{
#region Overrides of ValueInjection
/// <summary>
/// Injects the source object properties into the target object properties.
/// </summary>
/// <param name="source">The source object.</param>
/// <param name="target">The target object.</param>
protected override void Inject(object source, object target)
{
if (source == null || target == null)
return;
PropertyDescriptorCollection sourceProps = source.GetProps();
PropertyDescriptorCollection targetProps = target.GetProps();
//Get source properties length.
int length = sourceProps.Count;
//Loop over all source properties.
for (int index = 0; index < length; index++)
{
//Get current source property.
PropertyDescriptor sourceProp = sourceProps[index];
//Get target property with the same name.
PropertyDescriptor targetProp = targetProps.GetByName(SearchTargetName(sourceProp.Name));
//Get value.
object targetValue = GetTargetValue(source, sourceProp, targetProp);
//Update value.
SetTargetValue(target, targetProp, targetValue);
}
}
/// <summary>
/// Gets the target value.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="sourceProp">The source prop.</param>
/// <param name="targetProp">The target prop.</param>
/// <returns></returns>
protected virtual object GetTargetValue(object source, PropertyDescriptor sourceProp, PropertyDescriptor targetProp)
{
//Validate target property.
if (targetProp == null)
return null;
//Get the source property value.
object sourceValue = sourceProp.GetValue(source);
//Validate source value.
if (sourceValue == null)
return null;
//Declare the target property value.
object targetValue;
//Check if the property types match.
if (TypesMatch(sourceProp.PropertyType, targetProp.PropertyType))
{
//Get property value from the source object.
targetValue = sourceValue;
}
else
{
try
{
//Create a new type converter.
TypeConverter converter = TypeDescriptor.GetConverter(targetProp.PropertyType);
//Validate converter.
if (converter == null)
return null;
//Convert from the source to target type.
targetValue = converter.CanConvertFrom(sourceProp.PropertyType)
? converter.ConvertFrom(sourceValue)
: Convert.ChangeType(sourceValue, targetProp.PropertyType);
}
catch
{
//Log the exception here or rethrow.
return null;
}
}
return targetValue;
}
/// <summary>
/// Sets the target value.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="targetProp">The target prop.</param>
/// <param name="value">The value.</param>
protected virtual void SetTargetValue(object target, PropertyDescriptor targetProp, object value)
{
//If target value is valid set target value.
if (value != null)
targetProp.SetValue(target, value);
}
#endregion
}
}
And that’s it, a conversion will be made to match the target type, and to use it you just need to write something like this:
target.InjectFrom<NameValueInjection>(source);
Happy coding.