/// <summary>
 ///     Map a property from a message to a projection
 /// </summary>
 /// <typeparam name="TMessage">A message type</typeparam>
 /// <typeparam name="TProjection">A projection type</typeparam>
 /// <typeparam name="TValue">A type of projection property</typeparam>
 /// <param name="source">An argument builder that contains resulting mapper</param>
 /// <param name="projectionProperty">An expression that identifies a projection property</param>
 /// <param name="getValue">A function to extract a value from a message</param>
 /// <returns>An argument builder that contains resulting mapper</returns>
 public static IRegisterMappers <TMessage, TProjection> Map <TMessage, TProjection, TValue>(
     this IRegisterMappers <TMessage, TProjection> source,
     Expression <Func <TProjection, TValue> > projectionProperty,
     Func <TMessage, TValue> getValue)
 {
     return(source.Do(ReflectionHelpers.CreateSetOperation(projectionProperty), getValue));
 }
 /// <summary>
 ///     Add a property value from a message to a projection
 /// </summary>
 /// <typeparam name="TMessage">A message type</typeparam>
 /// <typeparam name="TProjection">A projection type</typeparam>
 /// <typeparam name="TValue">A type of projection property</typeparam>
 /// <param name="source">An argument builder that contains resulting mapper</param>
 /// <param name="projectionProperty">An expression that identifies a projection property</param>
 /// <param name="getValue">A function to extract a value from a message</param>
 /// <returns>An argument builder that contains resulting mapper</returns>
 public static IRegisterMappers <TMessage, TProjection> Add <TMessage, TProjection, TValue>(
     this IRegisterMappers <TMessage, TProjection> source,
     Expression <Func <TProjection, TValue> > projectionProperty,
     Func <TMessage, TValue> getValue) where TValue : IComparable <TValue>
 {
     return(source.Do(ReflectionHelpers.CreateBinaryOperation(ExpressionType.Add, projectionProperty), getValue));
 }
 private static IRegisterMappers <TMessage, TProjection> Do <TMessage, TProjection, TValue>(
     this IRegisterMappers <TMessage, TProjection> source,
     Action <TProjection, TValue> action,
     Func <TMessage, TValue> getValue)
 {
     return(source.Do((e, p) => action(p, getValue(e))));
 }
 /// <summary>
 ///     Set a property value
 /// </summary>
 /// <typeparam name="TMessage">A message type</typeparam>
 /// <typeparam name="TProjection">A projection type</typeparam>
 /// <typeparam name="TValue">A type of projection property</typeparam>
 /// <param name="source">An argument builder that contains resulting mapper</param>
 /// <param name="projectionProperty">An expression that identifies a projection property</param>
 /// <param name="value">A new value for the property</param>
 /// <returns>An argument builder that contains resulting mapper</returns>
 public static IRegisterMappers <TMessage, TProjection> Set <TMessage, TProjection, TValue>(
     this IRegisterMappers <TMessage, TProjection> source,
     Expression <Func <TProjection, TValue> > projectionProperty,
     TValue value)
 {
     return(source.Do((e, p) => ReflectionHelpers.CreateSetOperation(projectionProperty)(p, value)));
 }
 /// <summary>
 ///     Do an action with a projection using a message
 /// </summary>
 /// <typeparam name="TMessage">A message type</typeparam>
 /// <typeparam name="TProjection">A projection type</typeparam>
 /// <param name="source">An argument builder that contains resulting mapper</param>
 /// <param name="action">An action to perform on projection</param>
 /// <returns>An argument builder that contains resulting mapper</returns>
 public static IRegisterMappers <TMessage, TProjection> Do <TMessage, TProjection>(
     this IRegisterMappers <TMessage, TProjection> source,
     Action <TMessage, TProjection> action)
 {
     source.Register(Mapper <TMessage, TProjection> .Create(action));
     return(source);
 }
        /// <summary>
        ///     Map a property from a message with the same name as in a projection
        /// </summary>
        /// <typeparam name="TMessage">A message type</typeparam>
        /// <typeparam name="TProjection">A projection type</typeparam>
        /// <typeparam name="TValue">A type of projection property</typeparam>
        /// <param name="source">An argument builder that contains resulting mapper</param>
        /// <param name="projectionProperty">An expression that identifies a projection property</param>
        /// <returns>An argument builder that contains resulting mapper</returns>
        public static IRegisterMappers <TMessage, TProjection> Map <TMessage, TProjection, TValue>(
            this IRegisterMappers <TMessage, TProjection> source,
            Expression <Func <TProjection, TValue> > projectionProperty)
        {
            PropertyInfo propertyInfo = ReflectionHelpers.GetMessagePropertyInfo <TMessage, TProjection, TValue>(projectionProperty);

            return(source.Map(projectionProperty, e => ReflectionHelpers.GetPropertyValue <TMessage, TValue>(e, propertyInfo)));
        }
        /// <summary>
        ///     Add a property value from a message with the same name as in a projection
        /// </summary>
        /// <typeparam name="TMessage">A message type</typeparam>
        /// <typeparam name="TProjection">A projection type</typeparam>
        /// <typeparam name="TValue">A type of projection property</typeparam>
        /// <param name="source">An argument builder that contains resulting mapper</param>
        /// <param name="projectionProperty">An expression that identifies a projection property</param>
        /// <returns>An argument builder that contains resulting mapper</returns>
        public static IRegisterMappers <TMessage, TProjection> Add <TMessage, TProjection, TValue>(
            this IRegisterMappers <TMessage, TProjection> source,
            Expression <Func <TProjection, TValue> > projectionProperty)
            where TValue : IComparable <TValue>
        {
            PropertyInfo propertyInfo = ReflectionHelpers.GetMessagePropertyInfo <TMessage, TProjection, TValue>(projectionProperty);

            return(source.Add(projectionProperty, e => ReflectionHelpers.GetPropertyValue <TMessage, TValue>(e, propertyInfo)));
        }
 /// <summary>
 ///     Decrement a property value in a projection
 /// </summary>
 /// <typeparam name="TMessage">A message type</typeparam>
 /// <typeparam name="TProjection">A projection type</typeparam>
 /// <param name="source">An argument builder that contains resulting mapper</param>
 /// <param name="projectionProperty">An expression that identifies a projection property</param>
 /// <returns>An argument builder that contains resulting mapper</returns>
 public static IRegisterMappers <TMessage, TProjection> Decrement <TMessage, TProjection>(
     this IRegisterMappers <TMessage, TProjection> source,
     Expression <Func <TProjection, long> > projectionProperty)
 {
     return(source.Substract(projectionProperty, e => 1));
 }