dotnet-dynamic-linq/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.cs

143 lines
4.8 KiB
C#
Raw Permalink Normal View History

2018-02-11 20:55:29 -05:00
using PoweredSoft.DynamicLinq.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace PoweredSoft.DynamicLinq.Fluent
{
public partial class WhereBuilder : IQueryBuilder
2018-02-11 20:55:29 -05:00
{
2018-03-14 20:25:47 -04:00
public IQueryable Query { get; set; }
public Type QueryableType { get; set; }
public List<WhereBuilderCondition> Filters { get; protected set; } = new List<WhereBuilderCondition>();
public WhereBuilder(IQueryable query)
2018-02-11 20:55:29 -05:00
{
Query = query;
2018-03-14 20:25:47 -04:00
QueryableType = query.ElementType;
}
public bool IsNullCheckingEnabled { get; protected set; } = false;
public virtual WhereBuilder NullChecking(bool check = true)
{
IsNullCheckingEnabled = check;
return this;
}
public virtual WhereBuilder Compare(string path, ConditionOperators conditionOperators, object value,
QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField,
2019-03-19 18:01:09 -04:00
bool and = true, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false)
2018-03-14 20:25:47 -04:00
{
Filters.Add(new WhereBuilderCondition
{
And = and,
ConditionOperator = conditionOperators,
Path = path,
Value = value,
ConvertStrategy = convertStrategy,
CollectionHandling = collectionHandling,
2019-03-19 18:01:09 -04:00
StringComparisation = stringComparision,
Negate = negate
2018-03-14 20:25:47 -04:00
});
return this;
}
public virtual WhereBuilder SubQuery(Action<WhereBuilder> subQuery, bool and = true)
{
// create query builder for same type.
var qb = new WhereBuilder(Query);
qb.NullChecking(IsNullCheckingEnabled);
// callback.
subQuery(qb);
// create a query part.
var part = new WhereBuilderCondition();
part.And = and;
part.Conditions = qb.Filters;
Filters.Add(part);
//return self.
return this;
2018-02-11 20:55:29 -05:00
}
2018-03-14 20:25:47 -04:00
public virtual IQueryable Build()
2018-02-12 04:30:55 -05:00
{
// the query.
var query = Query;
2018-02-12 05:18:44 -05:00
if (Filters == null || Filters?.Count() == 0)
return query;
// shared parameter.
2018-03-14 20:25:47 -04:00
var sharedParameter = Expression.Parameter(QueryableType, "t");
// build the expression.
2018-03-14 20:25:47 -04:00
var filterExpressionMerged = BuildConditionExpression(sharedParameter, Filters);
// create the where expression.
var whereExpression = Expression.Call(typeof(Queryable), "Where", new[] { query.ElementType }, query.Expression, filterExpressionMerged);
// lets see what happens here.
query = query.Provider.CreateQuery(whereExpression);
2018-02-12 05:18:44 -05:00
2018-02-11 20:55:29 -05:00
return query;
}
2018-03-14 20:25:47 -04:00
protected virtual Expression BuildConditionExpression(ParameterExpression parameter, List<WhereBuilderCondition> filters)
2018-02-11 20:55:29 -05:00
{
2018-03-14 20:25:47 -04:00
Expression temp = null;
2018-02-11 20:55:29 -05:00
2018-02-12 04:35:27 -05:00
filters.ForEach(filter =>
2018-02-11 20:55:29 -05:00
{
2018-03-14 20:25:47 -04:00
Expression innerExpression;
2018-03-14 19:17:25 -04:00
if (filter.Conditions?.Any() == true)
2018-03-14 20:25:47 -04:00
innerExpression = BuildConditionExpression(parameter, filter.Conditions);
2018-02-11 20:55:29 -05:00
else
2018-03-14 20:25:47 -04:00
innerExpression = BuildConditionExpression(parameter, filter);
2018-02-11 20:55:29 -05:00
if (temp == null)
{
temp = innerExpression;
}
2018-02-11 20:55:29 -05:00
else
{
2018-03-14 20:25:47 -04:00
var body = ((LambdaExpression)temp).Body;
var innerEpressionBody = ((LambdaExpression)innerExpression).Body;
if (filter.And)
2018-03-14 20:25:47 -04:00
temp = Expression.Lambda(Expression.AndAlso(body, innerEpressionBody), parameter);
else
2018-03-14 20:25:47 -04:00
temp = Expression.Lambda(Expression.OrElse(body, innerEpressionBody), parameter);
}
2018-02-11 20:55:29 -05:00
});
return temp;
2018-02-11 20:55:29 -05:00
}
2018-03-14 20:25:47 -04:00
protected virtual Expression BuildConditionExpression(ParameterExpression parameter, WhereBuilderCondition filter)
2018-02-11 20:55:29 -05:00
{
2018-03-14 20:25:47 -04:00
var ret = QueryableHelpers.CreateConditionExpression(
parameter.Type,
filter.Path,
filter.ConditionOperator,
filter.Value,
filter.ConvertStrategy,
filter.CollectionHandling,
parameter: parameter,
2018-03-06 20:43:49 -05:00
nullChecking: IsNullCheckingEnabled,
2019-03-19 18:01:09 -04:00
stringComparision: filter.StringComparisation,
negate: filter.Negate
);
return ret;
2018-02-11 20:55:29 -05:00
}
}
}