Our ReflectionHelper class (and related classes used by it) are monsters, so I'll just post the relevant methods here:
Code:
public static class ReflectionHelper
{
    ...
    public static void SetPropertyValue(object instance, string propertyName, object value)
    {
        ArgumentHelper.RequireValue("instance", instance);
        PropertyInfo property = GetProperty(instance.GetType(), propertyName, BindingFlags.Instance);
        if (property == null)
        {
            throw new MissingMemberException(instance.GetType().Name, propertyName);
        }
        try
        {
            SetPropertyValueCore(instance, property, value);
        }
        catch (Exception x)
        {
            throw new MemberAccessException(
                string.Format(
                    "Failed to set property {0}.{1} to '{2}' on instance '{3}'",
                    instance.GetType().Name,
                    propertyName,
                    value ?? "<null>",
                    instance.ToString()),
                x);
        }
    }
    public static PropertyInfo GetProperty(Type searchType, string propertyName, BindingFlags bindingFlags)
    {
        return GetProperty(searchType, propertyName, bindingFlags, false);
    }
    public static PropertyInfo GetProperty(Type searchType, string propertyName, BindingFlags bindingFlags, bool throwExceptionIfMissing)
    {
        ArgumentHelper.RequireValue("searchType",   searchType);
        ArgumentHelper.RequireValue("propertyName", propertyName);
        bindingFlags |= BindingFlags.Public;
        bindingFlags |= BindingFlags.NonPublic;
        bindingFlags |= BindingFlags.DeclaredOnly;
        while (searchType != null)
        {
            foreach (PropertyInfo property in searchType.GetProperties(bindingFlags))
            {
                if (property.Name == propertyName)
                {
                    return property;
                }
            }
            if (searchType.IsInterface)
            {
                PropertyInfo inheritedInterfaceProperty;
                foreach (Type subInterfaceType in searchType.GetInterfaces())
                {
                    inheritedInterfaceProperty = GetProperty(
                        subInterfaceType, propertyName, bindingFlags);
                    if (inheritedInterfaceProperty != null)
                    {
                        return inheritedInterfaceProperty;
                    }
                }
            }
            else
            {
                searchType = searchType.BaseType;
            }
        }
        if (throwExceptionIfMissing)
        {
            throw new MissingMemberException(searchType.FullName, propertyName);
        }
        return null;
    }
    private static void SetPropertyValueCore(
        object instance,
        PropertyInfo property,
        object value)
    {
        try
        {
            property.SetValue(instance, value, null);
        }
        catch (InvalidCastException)
        {
            object convertedValue = Convert.ChangeType(value, property.PropertyType);
            property.SetValue(instance, convertedValue, null);
        }
    }
}
/// <summary>
/// A helper class for enforcing requirements on method and property arguments.
/// </summary>
/// <remarks>
/// Using this class allows you to write concise, declarative-style code
/// for enforcing argument requirements.  The methods provided cover the large
/// majority of such needs, freeing your code of "if/then" clutter while providing
/// consistent exception types and messages.
/// </remarks>
public static class ArgumentHelper
{
    /// <summary>
    /// Requires an argument to implement a given type
    /// (throwing an exception if it does not).
    /// </summary>
    /// <param name="requiredType">The type that the argument must implement.</param>
    /// <param name="argumentName">The actual name of the argument or property.</param>
    /// <param name="argumentValue">The value to check.</param>
    /// <exception cref="ArgumentOutOfRangeException">
    /// <paramRef>argumentValue</paramRef> does not implement
    /// <paramRef>requiredType</paramRef>.
    /// </exception>
    public static void RequireType(
        Type requiredType, string argumentName, object argumentValue)
    {
        RequireValue("requiredType", requiredType);
        RequireValue("argumentName", argumentName);
        if (argumentValue != null)
        {
            RequireType(requiredType, argumentName, argumentValue.GetType());
        }
    }
    /// <summary>
    /// Requires an argument to implement a given type
    /// (throwing an exception if it does not).
    /// </summary>
    /// <param name="requiredType">The type that the argument must implement.</param>
    /// <param name="argumentName">The actual name of the argument or property.</param>
    /// <param name="argumentType">The type to check.</param>
    /// <exception cref="ArgumentOutOfRangeException">
    /// <paramRef>argumentType</paramRef> does not implement
    /// <paramRef>requiredType</paramRef>.
    /// </exception>
    public static void RequireType(
        Type requiredType, string argumentName, Type argumentType)
    {
        RequireValue("requiredType", requiredType);
        RequireValue("argumentName", argumentName);
        RequireValue("argumentType", argumentType);
        if (!requiredType.IsAssignableFrom(argumentType))
        {
            string argumentTypeName;
            string requiredTypeName;
            if (argumentType.FullName != requiredType.FullName)
            {
                argumentTypeName = argumentType.FullName;
                requiredTypeName = requiredType.FullName;
            }
            else if (argumentType.AssemblyQualifiedName != requiredType.AssemblyQualifiedName)
            {
                argumentTypeName = argumentType.AssemblyQualifiedName;
                requiredTypeName = requiredType.AssemblyQualifiedName;
            }
            else
            {
                argumentTypeName = string.Format(
                    CultureInfo.CurrentCulture,
                    "{0} loaded from {1}",
                    argumentType.AssemblyQualifiedName,
                    SubstituteWhereEmpty(argumentType.Assembly.Location, "(unknown)"));
                requiredTypeName = string.Format(
                    CultureInfo.CurrentCulture,
                    "{0} loaded from {1}",
                    requiredType.AssemblyQualifiedName,
                    SubstituteWhereEmpty(requiredType.Assembly.Location, "(unknown)"));
            }
            throw new ArgumentOutOfRangeException(argumentName, argumentType,
                string.Format(
                    "Argument '{0}' type '{1}' is not assignable to type '{2}'.",
                    argumentName,
                    argumentTypeName,
                    requiredTypeName));
        }
    }
    /// <summary>
    /// Requires an argument to have a value
    /// (throwing an exception if it does not).
    /// </summary>
    /// <param name="argumentName">The actual name of the argument or property.</param>
    /// <param name="argumentValue">The collection to check.</param>
    /// <exception cref="ArgumentNullException">
    /// <paramRef>argumentName</paramRef> or <paramRef>argumentValue</paramRef>
    /// is <c>null</c>.
    /// </exception>
    /// <exception cref="ArgumentNotValuedException">
    /// <paramRef>argumentName</paramRef> or <paramRef>argumentValue</paramRef>
    /// has a trimmed length of zero.
    /// </exception>
    public static void RequireValue(string argumentName, object argumentValue)
    {
        if (argumentValue == null)
        {
            throw new ArgumentNullException(argumentName);
        }
        else
        {
            // TODO: make an IRequireValue interface for classes and services.
            // Then provide a way to register these interfaces by type,
            // and automatically register the two below.
            //
            // That way, this front-end service can always be used,
            // without know any details of how to determine if a "value" is present
            // (some types can be "unvalued" even when not null.)
            // It will also allow for when a separate service must be used,
            // such as the case for strings, because we can't subclass string
            // to put an HasValue() method on it ...
            switch (argumentValue.GetType().FullName)
            {
                case "System.String":
                    TextHelper.RequireValue(argumentName, argumentValue);
                    break;
                case "System.Text.StringBuilder":
                    TextHelper.RequireValue(argumentName, argumentValue.ToString());
                    break;
            }
        }
    }
    /// <summary>
    /// Requires a collection have at least one element
    /// (throwing an exception if it does not).
    /// </summary>
    /// <param name="argumentName">The actual name of the argument or property.</param>
    /// <param name="argumentValue">The collection to check.</param>
    /// <exception cref="ArgumentNullException">
    /// <paramRef>argumentName</paramRef> or <paramRef>argumentValue</paramRef>
    /// is <c>null</c>.
    /// </exception>
    /// <exception cref="ArgumentNotValuedException">
    /// <paramRef>argumentValue</paramRef> has no elements,
    /// or <paramRef>argumentName</paramRef> or <paramRef>argumentValue</paramRef>
    /// has a trimmed length of zero.
    /// </exception>
    public static void RequireNonEmptyCollection(
        string argumentName, ICollection argumentValue)
    {
        RequireValue(argumentName, argumentValue);
        if (argumentValue.Count == 0)
        {
            throw new ArgumentNotValuedException(argumentName, argumentValue,
                "The collection must have at least one element.");
        }
    }
    /// <summary>
    /// Return either the specified value, or its substitute if empty.
    /// </summary>
    /// <param name="valueToTry">The value to return, if not empty.</param>
    /// <param name="valueToSubstitute">The value to return if
    /// <paramref>valueToTry</paramref> is empty.</param>
    /// <returns><paramref>valueToTry</paramref> if not empty,
    /// otherwise <paramref>valueToSubstitute</paramref>.</returns>
    /// <remarks>
    /// Values of <b>Null</b> <see cref="DBNull.Value"/> are considered empty.
    /// Blank strings or strings containing only whitespace are also considered empty.
    /// </remarks>
    public static object SubstituteWhereEmpty(object valueToTry, object valueToSubstitute)
    {
        return (TextHelper.HasValue(valueToTry) ? valueToTry : valueToSubstitute);
    }
}
/// <summary>
/// Indicates that an argument, while not null, is still "unvalued"
/// in some way specific to the argument type, that makes it invalid
/// for use by the receiving method or property.
/// </summary>
/// <example>
/// <see cref="ArgumentHelper.RequireValue">
/// ArgumentHelper.RequireValue</see> requires arguments of type String and
/// StringBuilder to contain values with non-zero trimmed lengths.
/// <see cref="ArgumentHelper.RequireNonEmptyCollection">
/// ArgumentHelper.RequireNonEmptyCollection</see> requires specified
/// collections to have at least one element.
/// Both of these methods throw this type of exception
/// if their requirements are not met.
/// </example>
///
[Serializable]
public class ArgumentNotValuedException : ArgumentOutOfRangeException
{
    public ArgumentNotValuedException(
        string argumentName, object value, string message)
        : base(argumentName, value, message)
    {
    }
    public ocArgumentNotValuedException()
        : base()
    {
    }
    public ArgumentNotValuedException(string message, Exception innerException)
        : base(message, innerException)
    {
    }
    public ArgumentNotValuedException(string argumentName)
        : base(argumentName)
    {
    }
    protected ArgumentNotValuedException(
        SerializationInfo info,
        StreamingContext context)
        : base(info, context)
    {
    }
}
public static class TextHelper
{
    ...
    public static void RequireValue(string argumentName, object argumentValue)
    {
        if (argumentValue == null)
        {
            throw new ArgumentNullException(argumentName);
        }
        if (!HasValue(argumentValue))
        {
            throw new ArgumentNotValuedException(argumentName, argumentValue,
                "The argument must have a non-zero trimmed length.");
        }
    }
    /// <summary>
    /// Determines if a value is usable (non-<b>null</b> and non-blank).
    /// </summary>
    /// <param name="value">The value to check.</param>
    /// <returns>
    /// <b>true</b> if <paramref>value</paramref> is non-<b>null</b> and non-blank,
    /// otherwise <b>false</b>.
    /// </returns>
    public static bool HasValue(object value)
    {
        return (NullToBlankString(value).Trim().Length > 0);
    }
    public static string NullToBlankString(object parameter)
    {
        object cleanedParameter = DbNullToNull(parameter);
        return (cleanedParameter == null ? string.Empty : cleanedParameter.ToString());
    }
    public static object DbNullToNull(object parameter)
    {
        object result;
        if (parameter != null && parameter.GetType() == System.DBNull.Value.GetType())
        {
            result = null;
        }
        else
        {
            result = parameter;
        }
        return result;
    }
}