-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding the ability to build queries in stages (#157)
- Loading branch information
1 parent
3dc1d6d
commit 852682f
Showing
8 changed files
with
590 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Linq.Expressions; | ||
|
||
namespace Redis.OM | ||
{ | ||
/// <summary> | ||
/// Enables the efficient, dynamic composition of query predicates. | ||
/// credit to the author Ano Mepani whose <see href="https://www.c-sharpcorner.com/UploadFile/c42694/dynamic-query-in-linq-using-predicate-builder/">post</see> this class was taken from, with some light edits. | ||
/// </summary> | ||
internal static class PredicateBuilder | ||
{ | ||
/// <summary> | ||
/// Combines the first predicate with the second using the logical "and". | ||
/// </summary> | ||
/// <param name="first">The first expression.</param> | ||
/// <param name="second">The second expression.</param> | ||
/// <typeparam name="T">The parameter type for the expression.</typeparam> | ||
/// <returns>the combined expression.</returns> | ||
internal static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) | ||
{ | ||
return first.Compose(second, Expression.AndAlso); | ||
} | ||
|
||
/// <summary> | ||
/// Combines the first expression with the second using the specified merge function. | ||
/// </summary> | ||
private static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge) | ||
{ | ||
// zip parameters (map from parameters of second to parameters of first) | ||
var map = first.Parameters | ||
.Select((f, i) => new { f, s = second.Parameters[i] }) | ||
.ToDictionary(p => p.s, p => p.f); | ||
|
||
// replace parameters in the second lambda expression with the parameters in the first | ||
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); | ||
|
||
// create a merged lambda expression with parameters from the first expression | ||
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters); | ||
} | ||
|
||
private class ParameterRebinder : ExpressionVisitor | ||
{ | ||
private readonly Dictionary<ParameterExpression, ParameterExpression> _map; | ||
|
||
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) | ||
{ | ||
this._map = map ?? new Dictionary<ParameterExpression, ParameterExpression>(); | ||
} | ||
|
||
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) | ||
{ | ||
return new ParameterRebinder(map).Visit(exp); | ||
} | ||
|
||
protected override Expression VisitParameter(ParameterExpression p) | ||
{ | ||
ParameterExpression replacement; | ||
|
||
if (_map.TryGetValue(p, out replacement)) | ||
{ | ||
p = replacement; | ||
} | ||
|
||
return base.VisitParameter(p); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.