Пример #1
0
        /// <summary>
        /// Translates a given predicate for a given subtype.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated predicate's parameter.</typeparam>
        /// <returns>A translated predicate expression.</returns>
        public Expression <Func <TTranslatedSource, bool> > To <TTranslatedSource>()
            where TTranslatedSource : TSource
        {
            var s = predicate.Parameters[0];
            var t = Expression.Parameter(typeof(TTranslatedSource), s.Name);

            var binder = new ParameterBinder(s, t);

            return(Expression.Lambda <Func <TTranslatedSource, bool> >(
                       binder.Visit(predicate.Body), t));
        }
Пример #2
0
        /// <summary>
        /// Translates a given selector for a given subtype using it's source parameter.
        /// </summary>
        /// <typeparam name="V">The type of the translated selector's source parameter.</typeparam>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <V, U> > Source <V>()
            where V : T
        {
            var t = selector.Parameters[0];
            var v = Expression.Parameter(typeof(V), t.Name);

            var binder = new ParameterBinder(t, v);

            return(Expression.Lambda <Func <V, U> >(
                       binder.Visit(selector.Body), v));
        }
Пример #3
0
        /// <summary>
        /// Translates a given selector for a given subtype using it's source parameter.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated selector's source parameter.</typeparam>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <TTranslatedSource, TResult> > Source <TTranslatedSource>()
            where TTranslatedSource : TSource
        {
            var s = selector.Parameters[0];
            var t = Expression.Parameter(typeof(TTranslatedSource), s.Name);

            var binder = new ParameterBinder(s, t);

            return(Expression.Lambda <Func <TTranslatedSource, TResult> >(
                       binder.Visit(selector.Body), t));
        }
Пример #4
0
        /// <summary>
        /// Translates a given predicate for a given subtype.
        /// </summary>
        /// <typeparam name="U">The type of the translated predicate's parameter.</typeparam>
        /// <returns>A translated predicate expression.</returns>
        public Expression <Func <U, bool> > To <U>()
            where U : T
        {
            var t = predicate.Parameters[0];
            var u = Expression.Parameter(typeof(U), t.Name);

            var binder = new ParameterBinder(t, u);

            return(Expression.Lambda <Func <U, bool> >(
                       binder.Visit(predicate.Body), u));
        }
Пример #5
0
        /// <summary>
        /// Translates a given predicate for a given related type.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated predicate's parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given predicate to be injected into a new predicate.</param>
        /// <returns>A translated predicate expression.</returns>
        public Expression <Func <TTranslatedSource, bool> > To <TTranslatedSource>(Expression <Func <TTranslatedSource, Func <TSource, bool>, bool> > translation)
        {
            if (translation == null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var t = translation.Parameters[0];
            var s = translation.Parameters[1];

            var binder = new ParameterBinder(s, predicate);

            return(Expression.Lambda <Func <TTranslatedSource, bool> >(
                       binder.Visit(translation.Body), t));
        }
Пример #6
0
        /// <summary>
        /// Translates a given selector for a given related type using it's source parameter.
        /// </summary>
        /// <typeparam name="V">The type of the translated selector's source parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given selector to be injected into a new selector.</param>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <V, U> > Source <V>(Expression <Func <V, Func <T, U>, U> > translation)
        {
            if (translation == null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var v = translation.Parameters[0];
            var s = translation.Parameters[1];

            var binder = new ParameterBinder(s, selector);

            return(Expression.Lambda <Func <V, U> >(
                       binder.Visit(translation.Body), v));
        }
Пример #7
0
        /// <summary>
        /// Translates a given selector for a given related type using it's source parameter.
        /// </summary>
        /// <typeparam name="V">The type of the translated selector's source parameter.</typeparam>
        /// <param name="path">The path from the desired type to the given type.</param>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <V, U> > Source <V>(Expression <Func <V, T> > path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            var t = selector.Parameters[0];
            var v = path.Parameters[0];

            var binder = new ParameterBinder(t, path.Body);

            return(Expression.Lambda <Func <V, U> >(
                       binder.Visit(selector.Body), v));
        }
Пример #8
0
        /// <summary>
        /// Translates a given predicate for a given related type.
        /// </summary>
        /// <typeparam name="U">The type of the translated predicate's parameter.</typeparam>
        /// <param name="path">The path from the desired type to the given type.</param>
        /// <returns>A translated predicate expression.</returns>
        public Expression <Func <U, bool> > To <U>(Expression <Func <U, T> > path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            var t = predicate.Parameters[0];
            var u = path.Parameters[0];

            var binder = new ParameterBinder(t, path.Body);

            return(Expression.Lambda <Func <U, bool> >(
                       binder.Visit(predicate.Body), u));
        }
Пример #9
0
        /// <summary>
        /// Translates a given selector for a given related type using it's source parameter.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated selector's source parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given selector to be injected into a new selector.</param>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <TTranslatedSource, IEnumerable <TResult> > > Source <TTranslatedSource>(Expression <Func <TTranslatedSource, Func <TSource, TResult>, IEnumerable <TResult> > > translation)
        {
            if (translation == null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var t = translation.Parameters[0];
            var s = translation.Parameters[1];

            var binder = new ParameterBinder(s, selector);

            return(Expression.Lambda <Func <TTranslatedSource, IEnumerable <TResult> > >(
                       binder.Visit(translation.Body), t));
        }
Пример #10
0
        /// <summary>
        /// Translates a given selector for a given related type using it's source parameter.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated selector's source parameter.</typeparam>
        /// <param name="path">The path from the desired type to the given type.</param>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <TTranslatedSource, TResult> > Source <TTranslatedSource>(Expression <Func <TTranslatedSource, TSource> > path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            var s = selector.Parameters[0];
            var t = path.Parameters[0];

            var binder = new ParameterBinder(s, path.Body);

            return(Expression.Lambda <Func <TTranslatedSource, TResult> >(
                       binder.Visit(selector.Body), t));
        }
Пример #11
0
        /// <summary>
        /// Translates a given selector for a given related type using it's result parameter.
        /// </summary>
        /// <typeparam name="TTranslatedResult">The type of the translated selector's result parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given selector to be injected into a new selector.</param>
        /// <returns>A translated selector expression.</returns>
        public Expression <Func <TSource, TTranslatedResult> > Result <TTranslatedResult>(Expression <Func <TSource, Func <TSource, TResult>, TTranslatedResult> > translation)
        {
            if (translation is null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var s = translation.Parameters[0];
            var t = translation.Parameters[1];

            var binder = new ParameterBinder(t, selector);

            return(Expression.Lambda <Func <TSource, TTranslatedResult> >(
                       binder.Visit(translation.Body), s));
        }
Пример #12
0
        /// <summary>
        /// Translates a given predicate for a given related type.
        /// </summary>
        /// <typeparam name="U">The type of the translated predicate's parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given predicate to be injected into a new predicate.</param>
        /// <returns>A translated predicate expression.</returns>
        public Expression <Func <U, bool> > To <U>(Expression <Func <U, Func <T, bool>, bool> > translation)
        {
            if (translation == null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var u = translation.Parameters[0];
            var p = translation.Parameters[1];

            var binder = new ParameterBinder(p, predicate);

            return(Expression.Lambda <Func <U, bool> >(
                       binder.Visit(translation.Body), u));
        }
Пример #13
0
        /// <summary>
        /// Translates a given predicate for a given related type.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated predicate's parameter.</typeparam>
        /// <param name="path">The path from the desired type to the given type.</param>
        /// <returns>A translated predicate expression.</returns>
        public Expression <Func <TTranslatedSource, bool> > To <TTranslatedSource>(Expression <Func <TTranslatedSource, TSource> > path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            var s = predicate.Parameters[0];
            var t = path.Parameters[0];

            var binder = new ParameterBinder(s, path.Body);

            return(Expression.Lambda <Func <TTranslatedSource, bool> >(
                       binder.Visit(predicate.Body), t));
        }
Пример #14
0
        /// <summary>
        /// Translates a given selector for a given related type using it's source and result parameter
        /// and combines it with another given selector by merging their member bindings.
        /// </summary>
        /// <typeparam name="TTranslatedSource">The type of the translated selector's source parameter.</typeparam>
        /// <typeparam name="TTranslatedResult">The type of the translated selector's result parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given selector to be injected into a new selector.</param>
        /// <param name="value">The additional selector expression to combine.</param>
        /// <returns>A single translated and combined selector expression.</returns>
        public Expression <Func <TTranslatedSource, TTranslatedResult> > To <TTranslatedSource, TTranslatedResult>(Expression <Func <TTranslatedSource, Func <TSource, TResult>, TTranslatedResult> > translation, Expression <Func <TTranslatedSource, TTranslatedResult> > value = null)
        {
            if (translation == null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var s = translation.Parameters[0];
            var t = translation.Parameters[1];

            var binder = new ParameterBinder(t, selector);

            var result = Expression.Lambda <Func <TTranslatedSource, TTranslatedResult> >(
                binder.Visit(translation.Body), s);

            return(value != null?result.Apply(value) : result);
        }
Пример #15
0
        /// <summary>
        /// Translates a given selector for a given related type using it's source and result parameter
        /// and combines it with another given selector by merging their member bindings.
        /// </summary>
        /// <typeparam name="V">The type of the translated selector's source parameter.</typeparam>
        /// <typeparam name="W">The type of the translated selector's result parameter.</typeparam>
        /// <param name="translation">The translation from the desired type to the given type,
        /// using the initially given selector to be injected into a new selector.</param>
        /// <param name="value">The additional selector expression to combine.</param>
        /// <returns>A single translated and combined selector expression.</returns>
        public Expression <Func <V, W> > To <V, W>(Expression <Func <V, Func <T, U>, W> > translation, Expression <Func <V, W> > value = null)
        {
            if (translation == null)
            {
                throw new ArgumentNullException(nameof(translation));
            }

            var v = translation.Parameters[0];
            var s = translation.Parameters[1];

            var binder = new ParameterBinder(s, selector);

            var result = Expression.Lambda <Func <V, W> >(
                binder.Visit(translation.Body), v);

            return(value != null?result.Apply(value) : result);
        }
Пример #16
0
        /// <summary>
        /// Combines two given predicates using a conditional OR operation.
        /// </summary>
        /// <typeparam name="TSource">The type of the predicate's parameter.</typeparam>
        /// <param name="left">The first predicate expression to combine.</param>
        /// <param name="right">The second predicate expression to combine.</param>
        /// <returns>A single combined predicate expression.</returns>
        public static Expression <Func <TSource, bool> > Or <TSource>(this Expression <Func <TSource, bool> > left, Expression <Func <TSource, bool> > right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            var l = left.Parameters[0];
            var r = right.Parameters[0];

            var binder = new ParameterBinder(l, r);

            return(Expression.Lambda <Func <TSource, bool> >(
                       Expression.OrElse(binder.Visit(left.Body), right.Body), r));
        }
Пример #17
0
        /// <summary>
        /// Combines two given selectors by merging their member bindings.
        /// </summary>
        /// <typeparam name="TSource">The type of the selector's source parameter.</typeparam>
        /// <typeparam name="TResult">The type of the selector's result parameter.</typeparam>
        /// <param name="left">The first selector expression to combine.</param>
        /// <param name="right">The second selector expression to combine.</param>
        /// <returns>A single combined selector expression.</returns>
        public static Expression <Func <TSource, TResult> > Apply <TSource, TResult>(this Expression <Func <TSource, TResult> > left, Expression <Func <TSource, TResult> > right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            var leftInit  = left.Body as MemberInitExpression;
            var rightInit = right.Body as MemberInitExpression;

            var leftNew  = left.Body as NewExpression ?? leftInit?.NewExpression;
            var rightNew = right.Body as NewExpression ?? rightInit?.NewExpression;

            if (leftNew == null || rightNew == null)
            {
                throw new NotSupportedException("Only member init expressions and new expressions are supported yet.");
            }
            if (leftNew.Arguments.Any() || rightNew.Arguments.Any())
            {
                throw new NotSupportedException("Only parameterless constructors are supported yet.");
            }

            var leftBindings  = leftInit?.Bindings ?? Enumerable.Empty <MemberBinding>();
            var rightBindings = rightInit?.Bindings ?? Enumerable.Empty <MemberBinding>();

            var l = left.Parameters[0];
            var r = right.Parameters[0];

            var binder = new ParameterBinder(l, r);

            return(Expression.Lambda <Func <TSource, TResult> >(
                       binder.Visit(Expression.MemberInit(Expression.New(typeof(TResult)), leftBindings.Concat(rightBindings))), r));
        }