Archive for December, 2011

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.