Advancing well.
This commit is contained in:
parent
d2d28a9a45
commit
94d7b1c4d4
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicQuery",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicQuery.Cli", "PoweredSoft.DynamicQuery.Cli\PoweredSoft.DynamicQuery.Cli.csproj", "{7FC0F790-A8B9-4335-8D72-09797DEB0359}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicQuery.Cli", "PoweredSoft.DynamicQuery.Cli\PoweredSoft.DynamicQuery.Cli.csproj", "{7FC0F790-A8B9-4335-8D72-09797DEB0359}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.DynamicLinq", "..\DynamicLinq\PoweredSoft.DynamicLinq\PoweredSoft.DynamicLinq.csproj", "{E4E954E0-66FA-4D72-979A-FB2EF8356A90}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -27,6 +29,10 @@ Global
|
|||||||
{7FC0F790-A8B9-4335-8D72-09797DEB0359}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7FC0F790-A8B9-4335-8D72-09797DEB0359}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7FC0F790-A8B9-4335-8D72-09797DEB0359}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7FC0F790-A8B9-4335-8D72-09797DEB0359}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7FC0F790-A8B9-4335-8D72-09797DEB0359}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7FC0F790-A8B9-4335-8D72-09797DEB0359}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E4E954E0-66FA-4D72-979A-FB2EF8356A90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E4E954E0-66FA-4D72-979A-FB2EF8356A90}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E4E954E0-66FA-4D72-979A-FB2EF8356A90}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E4E954E0-66FA-4D72-979A-FB2EF8356A90}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -5,9 +5,39 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace PoweredSoft.DynamicQuery.Cli
|
namespace PoweredSoft.DynamicQuery.Cli
|
||||||
{
|
{
|
||||||
public class PersonQueryInterceptor : IBeforeQueryAlteredInterceptor<Person>
|
public class PersonQueryInterceptor : IQueryInterceptor
|
||||||
|
//, IBeforeQueryAlteredInterceptor<Person>
|
||||||
|
, IFilterInterceptor
|
||||||
{
|
{
|
||||||
public IQueryable<Person> InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable<Person> queryable) => queryable.Where(t => t.FirstName == "David");
|
public IQueryable<Person> InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable<Person> queryable)
|
||||||
|
=> queryable.Where(t => t.FirstName.StartsWith("Da"));
|
||||||
|
|
||||||
|
public IFilter InterceptFilter(IFilter filter)
|
||||||
|
{
|
||||||
|
if (filter is SimpleFilter)
|
||||||
|
{
|
||||||
|
var simpleFilter = filter as ISimpleFilter;
|
||||||
|
if (simpleFilter.Path == "FirstName" && simpleFilter.Value is string && ((string)simpleFilter.Value).Contains(","))
|
||||||
|
{
|
||||||
|
var firstNames = ((string) simpleFilter.Value).Split(',');
|
||||||
|
var filters = firstNames.Select(firstName => new SimpleFilter
|
||||||
|
{
|
||||||
|
Path = "FirstName",
|
||||||
|
Type = FilterType.Equal,
|
||||||
|
Value = firstName
|
||||||
|
}).Cast<IFilter>().ToList();
|
||||||
|
|
||||||
|
return new CompositeFilter
|
||||||
|
{
|
||||||
|
Type = FilterType.Composite,
|
||||||
|
Filters = filters,
|
||||||
|
And = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Person
|
public class Person
|
||||||
@ -30,18 +60,34 @@ namespace PoweredSoft.DynamicQuery.Cli
|
|||||||
{
|
{
|
||||||
var list = new List<Person>()
|
var list = new List<Person>()
|
||||||
{
|
{
|
||||||
new Person{ Id = 1, FirstName = "David", LastName = "Lebee "},
|
new Person{ Id = 1, FirstName = "David", LastName = "Lebee"},
|
||||||
new Person{ Id = 2, FirstName = "Michaela", LastName = "Lebee "},
|
new Person{ Id = 2, FirstName = "Michaela", LastName = "Lebee"},
|
||||||
new Person{ Id = 3, FirstName = "Zohra", LastName = "Lebee "},
|
new Person{ Id = 3, FirstName = "Zohra", LastName = "Lebee"},
|
||||||
new Person{ Id = 4, FirstName = "Eric", LastName = "Vickar "},
|
new Person{ Id = 4, FirstName = "Eric", LastName = "Vickar"},
|
||||||
new Person{ Id = 5, FirstName = "Susan", LastName = "Vickar "},
|
new Person{ Id = 5, FirstName = "Susan", LastName = "Vickar"},
|
||||||
};
|
};
|
||||||
|
|
||||||
var queryable = list.AsQueryable();
|
var queryable = list.AsQueryable();
|
||||||
|
|
||||||
var qb = new QueryBuilder();
|
var criteria = new QueryCriteria();
|
||||||
qb.AddInterceptor(new PersonQueryInterceptor());
|
|
||||||
qb.Execute(queryable, null);
|
criteria.Filters.Add(new SimpleFilter
|
||||||
|
{
|
||||||
|
Path = "LastName",
|
||||||
|
Value = "Lebee",
|
||||||
|
Type = FilterType.Equal,
|
||||||
|
});
|
||||||
|
|
||||||
|
criteria.Filters.Add(new SimpleFilter
|
||||||
|
{
|
||||||
|
Path = "FirstName",
|
||||||
|
Value = "David,Michaela",
|
||||||
|
Type = FilterType.Equal,
|
||||||
|
});
|
||||||
|
|
||||||
|
var handler = new QueryHandler();
|
||||||
|
handler.AddInterceptor(new PersonQueryInterceptor());
|
||||||
|
handler.Execute(queryable, criteria);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,17 @@
|
|||||||
{
|
{
|
||||||
public enum FilterType
|
public enum FilterType
|
||||||
{
|
{
|
||||||
Equals,
|
Equal,
|
||||||
Contains,
|
Contains,
|
||||||
StartsWith,
|
StartsWith,
|
||||||
EndsWith,
|
EndsWith,
|
||||||
Composite
|
Composite,
|
||||||
|
NotEqual,
|
||||||
|
GreaterThan,
|
||||||
|
LessThanOrEqual,
|
||||||
|
GreaterThanOrEqual,
|
||||||
|
LessThan,
|
||||||
|
In,
|
||||||
|
NotIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface IBeforeQueryAlteredInterceptor : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IQueryable InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable queryable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IBeforeQueryAlteredInterceptor<T> : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IQueryable<T> InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable<T> queryable);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface IBeforeQueryExecuteInterceptor : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IQueryable InterceptBeforeQuery(IQueryCriteria criteria, IQueryable queryable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IBeforeQueryExecuteInterceptor<T> : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IQueryable<T> InterceptBeforeQuery(IQueryCriteria criteria, IQueryable<T> queryable);
|
||||||
|
}
|
||||||
|
}
|
9
PoweredSoft.DynamicQuery.Core/IFilterInterceptor.cs
Normal file
9
PoweredSoft.DynamicQuery.Core/IFilterInterceptor.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface IFilterInterceptor : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IFilter InterceptFilter(IFilter filter);
|
||||||
|
}
|
||||||
|
}
|
7
PoweredSoft.DynamicQuery.Core/IGroupingInterceptor.cs
Normal file
7
PoweredSoft.DynamicQuery.Core/IGroupingInterceptor.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface IGroupingInterceptor : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IGroup InterceptGroup(IGroup group);
|
||||||
|
}
|
||||||
|
}
|
@ -1,55 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PoweredSoft.DynamicQuery.Core
|
|
||||||
{
|
|
||||||
public interface IQueryBuilder
|
|
||||||
{
|
|
||||||
IQueryResult Execute(IQueryable queryable, IQueryCriteria criteria);
|
|
||||||
Task<IQueryResult> ExecuteAsync(IQueryable queryable, IQueryCriteria criteria);
|
|
||||||
void AddInterceptor(IQueryInterceptor interceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IQueryInterceptor
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IBeforeQueryAlteredInterceptor : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IQueryable InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable queryable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IBeforeQueryAlteredInterceptor<T> : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IQueryable<T> InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable<T> queryable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFilterInteceptor : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IEnumerable<IFilter> InterceptFilter(IFilter filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IGroupingInteceptor : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IGroup InterceptGroup(IGroup group);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ISortInteceptor : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IEnumerable<ISort> InterceptSort(ISort sort);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IBeforeQueryExecuteInterceptor : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IQueryable InterceptBeforeQuery(IQueryCriteria criteria, IQueryable queryable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IBeforeQueryExecuteInterceptor<T> : IQueryInterceptor
|
|
||||||
{
|
|
||||||
IQueryable<T> InterceptBeforeQuery(IQueryCriteria criteria, IQueryable<T> queryable);
|
|
||||||
}
|
|
||||||
}
|
|
14
PoweredSoft.DynamicQuery.Core/IQueryHandler.cs
Normal file
14
PoweredSoft.DynamicQuery.Core/IQueryHandler.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface IQueryHandler
|
||||||
|
{
|
||||||
|
IQueryResult Execute(IQueryable queryable, IQueryCriteria criteria);
|
||||||
|
Task<IQueryResult> ExecuteAsync(IQueryable queryable, IQueryCriteria criteria);
|
||||||
|
void AddInterceptor(IQueryInterceptor interceptor);
|
||||||
|
}
|
||||||
|
}
|
7
PoweredSoft.DynamicQuery.Core/IQueryInterceptor.cs
Normal file
7
PoweredSoft.DynamicQuery.Core/IQueryInterceptor.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface IQueryInterceptor
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
9
PoweredSoft.DynamicQuery.Core/ISortInteceptor.cs
Normal file
9
PoweredSoft.DynamicQuery.Core/ISortInteceptor.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery.Core
|
||||||
|
{
|
||||||
|
public interface ISortInteceptor : IQueryInterceptor
|
||||||
|
{
|
||||||
|
IEnumerable<ISort> InterceptSort(ISort sort);
|
||||||
|
}
|
||||||
|
}
|
39
PoweredSoft.DynamicQuery/Extensions/FilterTypeExtensions.cs
Normal file
39
PoweredSoft.DynamicQuery/Extensions/FilterTypeExtensions.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using PoweredSoft.DynamicLinq;
|
||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery.Extensions
|
||||||
|
{
|
||||||
|
public static class FilterTypeExtensions
|
||||||
|
{
|
||||||
|
public static ConditionOperators? ConditionOperator(this FilterType filterType)
|
||||||
|
{
|
||||||
|
if (filterType == FilterType.Equal)
|
||||||
|
return ConditionOperators.Equal;
|
||||||
|
if (filterType == FilterType.NotEqual)
|
||||||
|
return ConditionOperators.NotEqual;
|
||||||
|
if (filterType == FilterType.GreaterThan)
|
||||||
|
return ConditionOperators.GreaterThan;
|
||||||
|
if (filterType == FilterType.GreaterThanOrEqual)
|
||||||
|
return ConditionOperators.GreaterThanOrEqual;
|
||||||
|
if (filterType == FilterType.LessThan)
|
||||||
|
return ConditionOperators.LessThan;
|
||||||
|
if (filterType == FilterType.LessThanOrEqual)
|
||||||
|
return ConditionOperators.LessThanOrEqual;
|
||||||
|
if (filterType == FilterType.StartsWith)
|
||||||
|
return ConditionOperators.StartsWith;
|
||||||
|
if (filterType == FilterType.EndsWith)
|
||||||
|
return ConditionOperators.EndsWith;
|
||||||
|
if (filterType == FilterType.Contains)
|
||||||
|
return ConditionOperators.Contains;
|
||||||
|
if (filterType == FilterType.In)
|
||||||
|
return ConditionOperators.In;
|
||||||
|
if (filterType == FilterType.NotIn)
|
||||||
|
return ConditionOperators.NotIn;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
PoweredSoft.DynamicQuery/Filter.cs
Normal file
28
PoweredSoft.DynamicQuery/Filter.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery
|
||||||
|
{
|
||||||
|
public abstract class Filter : IFilter
|
||||||
|
{
|
||||||
|
public bool? And { get; set; }
|
||||||
|
public FilterType Type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SimpleFilter : ISimpleFilter
|
||||||
|
{
|
||||||
|
public bool? And { get; set; }
|
||||||
|
public FilterType Type { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
public object Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompositeFilter : ICompositeFilter
|
||||||
|
{
|
||||||
|
public bool? And { get; set; }
|
||||||
|
public FilterType Type { get; set; } = FilterType.Composite;
|
||||||
|
public List<IFilter> Filters { get; set; }
|
||||||
|
}
|
||||||
|
}
|
13
PoweredSoft.DynamicQuery/Group.cs
Normal file
13
PoweredSoft.DynamicQuery/Group.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery
|
||||||
|
{
|
||||||
|
public class Group : IGroup
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public bool? Ascending { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\DynamicLinq\PoweredSoft.DynamicLinq\PoweredSoft.DynamicLinq.csproj" />
|
||||||
<ProjectReference Include="..\PoweredSoft.DynamicQuery.Core\PoweredSoft.DynamicQuery.Core.csproj" />
|
<ProjectReference Include="..\PoweredSoft.DynamicQuery.Core\PoweredSoft.DynamicQuery.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
using PoweredSoft.DynamicQuery.Core;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PoweredSoft.DynamicQuery
|
|
||||||
{
|
|
||||||
public class QueryBuilder : IQueryBuilder
|
|
||||||
{
|
|
||||||
protected List<IQueryInterceptor> Interceptors { get; } = new List<IQueryInterceptor>();
|
|
||||||
protected IQueryCriteria Criteria { get; set; }
|
|
||||||
protected IQueryable QueryableAtStart { get; private set; }
|
|
||||||
protected IQueryable CurrentQueryable { get; set; }
|
|
||||||
protected Type QueryableUnderlyingType => QueryableAtStart.ElementType;
|
|
||||||
private MethodInfo ApplyInterceptorsAndCriteriaMethod { get; } = typeof(QueryBuilder).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(t => t.Name == "ApplyInterceptorsAndCriteria" && t.IsGenericMethod);
|
|
||||||
|
|
||||||
protected virtual void Reset(IQueryable queryable, IQueryCriteria criteria)
|
|
||||||
{
|
|
||||||
//Criteria = criteria ?? throw new ArgumentNullException("criteria");
|
|
||||||
QueryableAtStart = queryable ?? throw new ArgumentNullException("queryable");
|
|
||||||
CurrentQueryable = QueryableAtStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void AddInterceptor(IQueryInterceptor interceptor)
|
|
||||||
{
|
|
||||||
if (interceptor == null) throw new ArgumentNullException("interceptor");
|
|
||||||
|
|
||||||
if (!Interceptors.Contains(interceptor))
|
|
||||||
Interceptors.Add(interceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void ApplyInterceptorsAndCriteria<T>()
|
|
||||||
{
|
|
||||||
ApplySimpleBeforeAlterInterceptors();
|
|
||||||
ApplyGenericBeforeAlterInterceptors<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyInterceptorsAndCriteria()
|
|
||||||
{
|
|
||||||
var genericMethod = ApplyInterceptorsAndCriteriaMethod.MakeGenericMethod(QueryableUnderlyingType);
|
|
||||||
genericMethod.Invoke(this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void ApplyGenericBeforeAlterInterceptors<T>()
|
|
||||||
{
|
|
||||||
var interceptors = Interceptors.Where(t => t is IBeforeQueryAlteredInterceptor<T>).Cast<IBeforeQueryAlteredInterceptor<T>>().ToList();
|
|
||||||
interceptors.ForEach(i => CurrentQueryable = i.InterceptQueryBeforeAltered(Criteria, (IQueryable<T>)CurrentQueryable));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void ApplySimpleBeforeAlterInterceptors()
|
|
||||||
{
|
|
||||||
var beforeAlterInterceptors = Interceptors.Where(t => t is IBeforeQueryAlteredInterceptor).Cast<IBeforeQueryAlteredInterceptor>().ToList();
|
|
||||||
beforeAlterInterceptors.ForEach(i => CurrentQueryable = i.InterceptQueryBeforeAltered(Criteria, CurrentQueryable));
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IQueryResult Execute(IQueryable queryable, IQueryCriteria criteria)
|
|
||||||
{
|
|
||||||
Reset(queryable, criteria);
|
|
||||||
ApplyInterceptorsAndCriteria();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public virtual Task<IQueryResult> ExecuteAsync(IQueryable queryable, IQueryCriteria criteria)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
PoweredSoft.DynamicQuery/QueryCriteria.cs
Normal file
17
PoweredSoft.DynamicQuery/QueryCriteria.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery
|
||||||
|
{
|
||||||
|
public class QueryCriteria : IQueryCriteria
|
||||||
|
{
|
||||||
|
public int? Page { get; set; }
|
||||||
|
public int? PageSize { get; set; }
|
||||||
|
public List<ISort> Sorts { get; set; } = new List<ISort>();
|
||||||
|
public List<IFilter> Filters { get; set; } = new List<IFilter>();
|
||||||
|
public List<IGroup> Groups { get; set; } = new List<IGroup>();
|
||||||
|
public List<IAggregate> Aggregates { get; set; } = new List<IAggregate>();
|
||||||
|
}
|
||||||
|
}
|
134
PoweredSoft.DynamicQuery/QueryHandler.cs
Normal file
134
PoweredSoft.DynamicQuery/QueryHandler.cs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
using PoweredSoft.DynamicLinq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PoweredSoft.DynamicLinq.Fluent;
|
||||||
|
using PoweredSoft.DynamicQuery.Extensions;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery
|
||||||
|
{
|
||||||
|
public class QueryHandler : IQueryHandler
|
||||||
|
{
|
||||||
|
protected List<IQueryInterceptor> Interceptors { get; } = new List<IQueryInterceptor>();
|
||||||
|
protected IQueryCriteria Criteria { get; set; }
|
||||||
|
protected IQueryable QueryableAtStart { get; private set; }
|
||||||
|
protected IQueryable CurrentQueryable { get; set; }
|
||||||
|
protected Type QueryableUnderlyingType => QueryableAtStart.ElementType;
|
||||||
|
private MethodInfo ApplyInterceptorsAndCriteriaMethod { get; } = typeof(QueryHandler).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(t => t.Name == "ApplyInterceptorsAndCriteria" && t.IsGenericMethod);
|
||||||
|
|
||||||
|
protected virtual void Reset(IQueryable queryable, IQueryCriteria criteria)
|
||||||
|
{
|
||||||
|
Criteria = criteria ?? throw new ArgumentNullException("criteria");
|
||||||
|
QueryableAtStart = queryable ?? throw new ArgumentNullException("queryable");
|
||||||
|
CurrentQueryable = QueryableAtStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AddInterceptor(IQueryInterceptor interceptor)
|
||||||
|
{
|
||||||
|
if (interceptor == null) throw new ArgumentNullException("interceptor");
|
||||||
|
|
||||||
|
if (!Interceptors.Contains(interceptor))
|
||||||
|
Interceptors.Add(interceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplyInterceptorsAndCriteria<T>()
|
||||||
|
{
|
||||||
|
ApplySimpleBeforeAlterInterceptors();
|
||||||
|
ApplyGenericBeforeAlterInterceptors<T>();
|
||||||
|
ApplyFilters<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual ConditionOperators? ResolveFromOrDefault(FilterType filterType) =>
|
||||||
|
filterType.ConditionOperator();
|
||||||
|
|
||||||
|
protected virtual ConditionOperators ResolveFrom(FilterType filterType)
|
||||||
|
{
|
||||||
|
var ret = ResolveFromOrDefault(filterType);
|
||||||
|
if (ret == null)
|
||||||
|
throw new NotSupportedException($"{filterType} is not supported");
|
||||||
|
|
||||||
|
return ret.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplyFilters<T>()
|
||||||
|
{
|
||||||
|
CurrentQueryable = CurrentQueryable.Query(whereBuilder =>
|
||||||
|
{
|
||||||
|
Criteria.Filters.ForEach(filter => ApplyFilter(whereBuilder, filter));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplyFilter(WhereBuilder whereBuilder, IFilter filter)
|
||||||
|
{
|
||||||
|
var transformedFilter = InterceptFilter(filter);
|
||||||
|
if (transformedFilter is ISimpleFilter)
|
||||||
|
ApplySimpleFilter(whereBuilder, transformedFilter as ISimpleFilter);
|
||||||
|
else if (transformedFilter is ICompositeFilter)
|
||||||
|
AppleCompositeFilter(whereBuilder, transformedFilter as ICompositeFilter);
|
||||||
|
else
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void AppleCompositeFilter(WhereBuilder whereBuilder, ICompositeFilter filter)
|
||||||
|
{
|
||||||
|
whereBuilder.SubQuery(subWhereBuilder => filter.Filters.ForEach(subFilter => ApplyFilter(subWhereBuilder, subFilter)), filter.And == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplySimpleFilter(WhereBuilder whereBuilder, ISimpleFilter filter)
|
||||||
|
{
|
||||||
|
var resolvedConditionOperator = ResolveFrom(filter.Type);
|
||||||
|
whereBuilder.Compare(filter.Path, resolvedConditionOperator, filter.Value, and: filter.And == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IFilter InterceptFilter(IFilter filter)
|
||||||
|
{
|
||||||
|
var ret = Interceptors.Where(t => t is IFilterInterceptor)
|
||||||
|
.Cast<IFilterInterceptor>()
|
||||||
|
.Aggregate(filter, (previousFilter, interceptor) => interceptor.InterceptFilter(previousFilter));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyInterceptorsAndCriteria()
|
||||||
|
{
|
||||||
|
var genericMethod = ApplyInterceptorsAndCriteriaMethod.MakeGenericMethod(QueryableUnderlyingType);
|
||||||
|
genericMethod.Invoke(this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplyGenericBeforeAlterInterceptors<T>()
|
||||||
|
{
|
||||||
|
CurrentQueryable = Interceptors
|
||||||
|
.Where(t => t is IBeforeQueryAlteredInterceptor<T>)
|
||||||
|
.Cast<IBeforeQueryAlteredInterceptor<T>>()
|
||||||
|
.Aggregate((IQueryable<T>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptQueryBeforeAltered(Criteria, prev));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplySimpleBeforeAlterInterceptors()
|
||||||
|
{
|
||||||
|
CurrentQueryable = Interceptors
|
||||||
|
.Where(t => t is IBeforeQueryAlteredInterceptor)
|
||||||
|
.Cast<IBeforeQueryAlteredInterceptor>()
|
||||||
|
.Aggregate(CurrentQueryable, (prev, interceptor) => interceptor.InterceptQueryBeforeAltered(Criteria, prev));
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IQueryResult Execute(IQueryable queryable, IQueryCriteria criteria)
|
||||||
|
{
|
||||||
|
Reset(queryable, criteria);
|
||||||
|
ApplyInterceptorsAndCriteria();
|
||||||
|
var debug = CurrentQueryable.ToObjectList();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual Task<IQueryResult> ExecuteAsync(IQueryable queryable, IQueryCriteria criteria)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
PoweredSoft.DynamicQuery/Sort.cs
Normal file
13
PoweredSoft.DynamicQuery/Sort.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
|
||||||
|
namespace PoweredSoft.DynamicQuery
|
||||||
|
{
|
||||||
|
public class Sort : ISort
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public bool? Ascending { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user