From b1db7a36043d580aaec084150e02b8e6d229f112 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 12 Feb 2018 03:30:55 -0600 Subject: [PATCH] added query convert strategy. --- PoweredSoft.DynamicLinq/Constants.cs | 6 +++ .../Extensions/QueryableExtensions.cs | 5 ++- .../Fluent/QueryBuilder.cs | 39 ++++++++++++------- .../Fluent/QueryFilterPart.cs | 3 +- .../Helpers/QueryableHelpers.cs | 11 ++++++ 5 files changed, 47 insertions(+), 17 deletions(-) diff --git a/PoweredSoft.DynamicLinq/Constants.cs b/PoweredSoft.DynamicLinq/Constants.cs index 4cb0a85..950437e 100644 --- a/PoweredSoft.DynamicLinq/Constants.cs +++ b/PoweredSoft.DynamicLinq/Constants.cs @@ -19,6 +19,12 @@ namespace PoweredSoft.DynamicLinq EndsWith } + public enum QueryConvertStrategy + { + LeaveAsIs, + ConvertConstantToComparedPropertyOrField + } + internal static class Constants { internal static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains"); diff --git a/PoweredSoft.DynamicLinq/Extensions/QueryableExtensions.cs b/PoweredSoft.DynamicLinq/Extensions/QueryableExtensions.cs index 2594fe0..f4fa69f 100644 --- a/PoweredSoft.DynamicLinq/Extensions/QueryableExtensions.cs +++ b/PoweredSoft.DynamicLinq/Extensions/QueryableExtensions.cs @@ -11,9 +11,10 @@ namespace PoweredSoft.DynamicLinq.Extensions { public static class QueryableExtensions { - public static IQueryable Where(this IQueryable query, string path, ConditionOperators conditionOperator, object value, bool convertConstantToLeftOperator = true) + public static IQueryable Where(this IQueryable query, string path, ConditionOperators conditionOperator, object value, + QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField) { - query = query.Query(qb => qb.Compare(path, conditionOperator, value, convertConstantToLeftOperator: convertConstantToLeftOperator)); + query = query.Query(qb => qb.Compare(path, conditionOperator, value, convertStrategy: convertStrategy)); return query; } diff --git a/PoweredSoft.DynamicLinq/Fluent/QueryBuilder.cs b/PoweredSoft.DynamicLinq/Fluent/QueryBuilder.cs index 10f8a37..32bf74d 100644 --- a/PoweredSoft.DynamicLinq/Fluent/QueryBuilder.cs +++ b/PoweredSoft.DynamicLinq/Fluent/QueryBuilder.cs @@ -21,8 +21,9 @@ namespace PoweredSoft.DynamicLinq.Fluent Query = query; } - public QueryBuilder Compare(string path, ConditionOperators conditionOperators, object value, - bool convertConstantToLeftOperator = true, bool and = true) + public virtual QueryBuilder Compare(string path, ConditionOperators conditionOperators, object value, + QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, + bool and = true) { Parts.Add(new QueryFilterPart { @@ -30,13 +31,13 @@ namespace PoweredSoft.DynamicLinq.Fluent ConditionOperator = conditionOperators, Path = path, Value = value, - ConvertConstantToLeftOperator = convertConstantToLeftOperator + ConvertStrategy = convertStrategy }); return this; } - public QueryBuilder SubQuery(Action> subQuery, bool and = true) + public virtual QueryBuilder SubQuery(Action> subQuery, bool and = true) { // create query builder for same type. var qb = new QueryBuilder(Query); @@ -54,11 +55,11 @@ namespace PoweredSoft.DynamicLinq.Fluent return this; } - public QueryBuilder And(string path, ConditionOperators conditionOperator, object value, bool convertConstantToLeftOperator = true) - => Compare(path, conditionOperator, value, convertConstantToLeftOperator: convertConstantToLeftOperator, and: true); + public QueryBuilder And(string path, ConditionOperators conditionOperator, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField) + => Compare(path, conditionOperator, value, convertStrategy: convertStrategy, and: true); - public QueryBuilder Or(string path, ConditionOperators conditionOperator, object value, bool convertConstantToLeftOperator = true) - => Compare(path, conditionOperator, value, convertConstantToLeftOperator: convertConstantToLeftOperator, and: false); + public QueryBuilder Or(string path, ConditionOperators conditionOperator, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField) + => Compare(path, conditionOperator, value, convertStrategy: convertStrategy, and: false); public QueryBuilder And(Action> subQuery) => SubQuery(subQuery, true); @@ -66,16 +67,28 @@ namespace PoweredSoft.DynamicLinq.Fluent public QueryBuilder Or(Action> subQuery) => SubQuery(subQuery, false); - public IQueryable Build() + public virtual IQueryable Build() + { + // the query. + var query = Query; + + // execute the filters. + query = ExecuteFilters(query); + + + return query; + } + + protected virtual IQueryable ExecuteFilters(IQueryable query) { var parameter = Expression.Parameter(typeof(T), "t"); var expression = BuildExpression(parameter, Parts); var lambda = Expression.Lambda>(expression, parameter); - var query = Query.Where(lambda); + query = query.Where(lambda); return query; } - protected Expression BuildExpression(ParameterExpression parameter, List parts) + protected virtual Expression BuildExpression(ParameterExpression parameter, List parts) { Expression ret = null; @@ -96,10 +109,10 @@ namespace PoweredSoft.DynamicLinq.Fluent return ret; } - private Expression BuildExpression(ParameterExpression parameter, QueryFilterPart part) + protected virtual Expression BuildExpression(ParameterExpression parameter, QueryFilterPart part) { var member = QueryableHelpers.ResolvePathForExpression(parameter, part.Path); - var constant = part.ConvertConstantToLeftOperator ? QueryableHelpers.GetConstantSameAsLeftOperator(member, part.Value) : Expression.Constant(part.Value); + var constant = QueryableHelpers.ResolveConstant(member, part.Value, part.ConvertStrategy); var expression = QueryableHelpers.GetConditionExpressionForMember(parameter, member, part.ConditionOperator, constant); return expression; } diff --git a/PoweredSoft.DynamicLinq/Fluent/QueryFilterPart.cs b/PoweredSoft.DynamicLinq/Fluent/QueryFilterPart.cs index 42b88a9..d14de56 100644 --- a/PoweredSoft.DynamicLinq/Fluent/QueryFilterPart.cs +++ b/PoweredSoft.DynamicLinq/Fluent/QueryFilterPart.cs @@ -12,8 +12,7 @@ namespace PoweredSoft.DynamicLinq.Fluent public ConditionOperators ConditionOperator { get; set; } public object Value { get; set; } public bool And { get; set; } - public bool ConvertConstantToLeftOperator { get; set; } - + public QueryConvertStrategy ConvertStrategy { get; set; } public List Parts { get; set; } = new List(); } } diff --git a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs index 5661841..d8f988f 100644 --- a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs +++ b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs @@ -80,5 +80,16 @@ namespace PoweredSoft.DynamicLinq.Helpers object convertedValue = TypeHelpers.ConvertFrom(memberType, value); return Expression.Constant(convertedValue); } + + public static ConstantExpression ResolveConstant(Expression member, object value, QueryConvertStrategy convertStrategy) + { + if (convertStrategy == QueryConvertStrategy.LeaveAsIs) + return Expression.Constant(value); + + if (convertStrategy == QueryConvertStrategy.ConvertConstantToComparedPropertyOrField) + return QueryableHelpers.GetConstantSameAsLeftOperator(member, value); + + throw new NotSupportedException($"{convertStrategy} supplied is not recognized"); + } } }