supporting in and not in.

This commit is contained in:
David Lebée
2018-03-06 21:04:54 -06:00
parent 47f31d5b74
commit 60dedaecf4
5 changed files with 150 additions and 5 deletions
+3 -1
View File
@@ -17,7 +17,9 @@ namespace PoweredSoft.DynamicLinq
LessThanOrEqual,
Contains,
StartsWith,
EndsWith
EndsWith,
In,
NotIn
}
public enum QueryConvertStrategy
@@ -118,5 +118,27 @@ namespace PoweredSoft.DynamicLinq.Fluent
public QueryBuilderBase OrEndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> Or(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
#endregion
#region In
public QueryBuilderBase In(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> And(path, ConditionOperators.In, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
public QueryBuilderBase AndIn(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> And(path, ConditionOperators.In, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
public QueryBuilderBase OrIn(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> Or(path, ConditionOperators.In, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
#endregion
#region NotIn
public QueryBuilderBase NotIn(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> And(path, ConditionOperators.NotIn, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
public QueryBuilderBase AndNotIn(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> And(path, ConditionOperators.NotIn, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
public QueryBuilderBase OrNotIn(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
=> Or(path, ConditionOperators.NotIn, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision);
#endregion
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
@@ -151,6 +152,17 @@ namespace PoweredSoft.DynamicLinq.Helpers
return query;
}
/*
* var methodInfo = typeof(List<Guid>).GetMethod("Contains", new Type[] { typeof(Guid) });
var list = Expression.Constant(ids);
var param = Expression.Parameter(typeof(T), "t");
var value = Expression.PropertyOrField(param, idField);
var body = Expression.Call(list, methodInfo, value);
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
query = query.Where(lambda);
*/
internal static Expression InternalCreateFilterExpression(int recursionStep, Type type, ParameterExpression parameter, Expression current, List<string> parts,
ConditionOperators condition, object value, QueryConvertStrategy convertStrategy, QueryCollectionHandling collectionHandling, bool nullChecking, StringComparison? stringComparison)
{
@@ -169,10 +181,17 @@ namespace PoweredSoft.DynamicLinq.Helpers
// create the expression and return it.
if (isLast)
{
var constant = QueryableHelpers.ResolveConstant(memberExpression, value, convertStrategy);
var filterExpression = QueryableHelpers.GetConditionExpressionForMember(parameter, memberExpression, condition, constant, stringComparison);
var lambda = Expression.Lambda(filterExpression, parameter);
return lambda;
if (condition == ConditionOperators.In || condition == ConditionOperators.NotIn)
{
return InAndNotIn(parameter, condition, value, convertStrategy, memberExpression);
}
else
{
var constant = QueryableHelpers.ResolveConstant(memberExpression, value, convertStrategy);
var filterExpression = QueryableHelpers.GetConditionExpressionForMember(parameter, memberExpression, condition, constant, stringComparison);
var lambda = Expression.Lambda(filterExpression, parameter);
return lambda;
}
}
// null check.
@@ -212,6 +231,42 @@ namespace PoweredSoft.DynamicLinq.Helpers
}
}
public static Expression InAndNotIn(ParameterExpression parameter, ConditionOperators condition, object value, QueryConvertStrategy convertStrategy, MemberExpression memberExpression)
{
var enumerableValue = value as IEnumerable;
if (enumerableValue == null)
throw new Exception($"to use {ConditionOperators.In} your value must at least be IEnumerable");
var enumerableType = GetEnumerableType(enumerableValue);
var finalType = convertStrategy == QueryConvertStrategy.ConvertConstantToComparedPropertyOrField ? memberExpression.Type : enumerableType;
var genericListOfEnumerableType = typeof(List<>).MakeGenericType(memberExpression.Type);
var containsMethod = genericListOfEnumerableType.GetMethod("Contains", new Type[] { finalType });
var list = Activator.CreateInstance(genericListOfEnumerableType) as IList;
foreach (var o in enumerableValue)
{
if (convertStrategy == QueryConvertStrategy.ConvertConstantToComparedPropertyOrField)
list.Add(TypeHelpers.ConvertFrom(memberExpression.Type, o));
else
list.Add(o);
}
var body = Expression.Call(Expression.Constant(list), containsMethod, memberExpression) as Expression;
if (condition == ConditionOperators.NotIn)
body = Expression.Not(body);
var lambda = Expression.Lambda(body, parameter);
return lambda;
}
private static Type GetEnumerableType(IEnumerable enumerableValue)
{
foreach (var o in enumerableValue)
return o.GetType();
return null;
}
public static MethodInfo GetCollectionMethod(QueryCollectionHandling collectionHandling)
{
if (collectionHandling == QueryCollectionHandling.All)