ExpressionFuncExtender.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. using System;
  2. using System.Linq;
  3. using System.Linq.Expressions;
  4. namespace Abp.Specifications
  5. {
  6. /// <summary>
  7. /// Represents the extender for Expression[Func[T, bool]] type.
  8. /// This is part of the solution which solves
  9. /// the expression parameter problem when going to Entity Framework.
  10. /// For more information about this solution please refer to http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx.
  11. /// </summary>
  12. public static class ExpressionFuncExtender
  13. {
  14. private static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
  15. {
  16. // build parameter map (from parameters of second to parameters of first)
  17. var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
  18. // replace parameters in the second lambda expression with parameters from the first
  19. var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
  20. // apply composition of lambda expression bodies to parameters from the first expression
  21. return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
  22. }
  23. /// <summary>
  24. /// Combines two given expressions by using the AND semantics.
  25. /// </summary>
  26. /// <typeparam name="T">The type of the object.</typeparam>
  27. /// <param name="first">The first part of the expression.</param>
  28. /// <param name="second">The second part of the expression.</param>
  29. /// <returns>The combined expression.</returns>
  30. public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
  31. {
  32. return first.Compose(second, Expression.AndAlso);
  33. }
  34. /// <summary>
  35. /// Combines two given expressions by using the OR semantics.
  36. /// </summary>
  37. /// <typeparam name="T">The type of the object.</typeparam>
  38. /// <param name="first">The first part of the expression.</param>
  39. /// <param name="second">The second part of the expression.</param>
  40. /// <returns>The combined expression.</returns>
  41. public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
  42. {
  43. return first.Compose(second, Expression.OrElse);
  44. }
  45. }
  46. }