From d2d28a9a456c3ae9ac64d245cafa6bbdc80ff6ba Mon Sep 17 00:00:00 2001 From: David Lebee Date: Wed, 17 Oct 2018 18:30:55 -0500 Subject: [PATCH] Add project files. --- DynamicQuery.sln | 37 ++++++++++ .../PoweredSoft.DynamicQuery.Cli.csproj | 13 ++++ PoweredSoft.DynamicQuery.Cli/Program.cs | 47 ++++++++++++ .../AggregateType.cs | 11 +++ PoweredSoft.DynamicQuery.Core/FilterType.cs | 11 +++ PoweredSoft.DynamicQuery.Core/IAggregate.cs | 8 +++ .../ICompositeFilter.cs | 9 +++ PoweredSoft.DynamicQuery.Core/IFilter.cs | 8 +++ PoweredSoft.DynamicQuery.Core/IGroup.cs | 8 +++ .../IQueryBuilder.cs | 55 ++++++++++++++ .../IQueryCriteria.cs | 16 +++++ PoweredSoft.DynamicQuery.Core/IQueryResult.cs | 29 ++++++++ .../ISimpleFilter.cs | 8 +++ PoweredSoft.DynamicQuery.Core/ISort.cs | 8 +++ .../PoweredSoft.DynamicQuery.Core.csproj | 7 ++ .../PoweredSoft.DynamicQuery.csproj | 11 +++ PoweredSoft.DynamicQuery/QueryBuilder.cs | 72 +++++++++++++++++++ 17 files changed, 358 insertions(+) create mode 100644 DynamicQuery.sln create mode 100644 PoweredSoft.DynamicQuery.Cli/PoweredSoft.DynamicQuery.Cli.csproj create mode 100644 PoweredSoft.DynamicQuery.Cli/Program.cs create mode 100644 PoweredSoft.DynamicQuery.Core/AggregateType.cs create mode 100644 PoweredSoft.DynamicQuery.Core/FilterType.cs create mode 100644 PoweredSoft.DynamicQuery.Core/IAggregate.cs create mode 100644 PoweredSoft.DynamicQuery.Core/ICompositeFilter.cs create mode 100644 PoweredSoft.DynamicQuery.Core/IFilter.cs create mode 100644 PoweredSoft.DynamicQuery.Core/IGroup.cs create mode 100644 PoweredSoft.DynamicQuery.Core/IQueryBuilder.cs create mode 100644 PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs create mode 100644 PoweredSoft.DynamicQuery.Core/IQueryResult.cs create mode 100644 PoweredSoft.DynamicQuery.Core/ISimpleFilter.cs create mode 100644 PoweredSoft.DynamicQuery.Core/ISort.cs create mode 100644 PoweredSoft.DynamicQuery.Core/PoweredSoft.DynamicQuery.Core.csproj create mode 100644 PoweredSoft.DynamicQuery/PoweredSoft.DynamicQuery.csproj create mode 100644 PoweredSoft.DynamicQuery/QueryBuilder.cs diff --git a/DynamicQuery.sln b/DynamicQuery.sln new file mode 100644 index 0000000..779a18f --- /dev/null +++ b/DynamicQuery.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicQuery.Core", "PoweredSoft.DynamicQuery.Core\PoweredSoft.DynamicQuery.Core.csproj", "{E614658D-6852-4405-B5BE-3695C3E96B13}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicQuery", "PoweredSoft.DynamicQuery\PoweredSoft.DynamicQuery.csproj", "{A9F74387-6B09-423A-96BC-F8FF345193EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicQuery.Cli", "PoweredSoft.DynamicQuery.Cli\PoweredSoft.DynamicQuery.Cli.csproj", "{7FC0F790-A8B9-4335-8D72-09797DEB0359}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E614658D-6852-4405-B5BE-3695C3E96B13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E614658D-6852-4405-B5BE-3695C3E96B13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E614658D-6852-4405-B5BE-3695C3E96B13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E614658D-6852-4405-B5BE-3695C3E96B13}.Release|Any CPU.Build.0 = Release|Any CPU + {A9F74387-6B09-423A-96BC-F8FF345193EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9F74387-6B09-423A-96BC-F8FF345193EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9F74387-6B09-423A-96BC-F8FF345193EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9F74387-6B09-423A-96BC-F8FF345193EE}.Release|Any CPU.Build.0 = Release|Any CPU + {7FC0F790-A8B9-4335-8D72-09797DEB0359}.Debug|Any CPU.ActiveCfg = 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.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3770CB3C-28E4-4C15-A537-4DA38CFBA4F3} + EndGlobalSection +EndGlobal diff --git a/PoweredSoft.DynamicQuery.Cli/PoweredSoft.DynamicQuery.Cli.csproj b/PoweredSoft.DynamicQuery.Cli/PoweredSoft.DynamicQuery.Cli.csproj new file mode 100644 index 0000000..9aff51a --- /dev/null +++ b/PoweredSoft.DynamicQuery.Cli/PoweredSoft.DynamicQuery.Cli.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp2.1 + + + + + + + + diff --git a/PoweredSoft.DynamicQuery.Cli/Program.cs b/PoweredSoft.DynamicQuery.Cli/Program.cs new file mode 100644 index 0000000..8bdf545 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Cli/Program.cs @@ -0,0 +1,47 @@ +using PoweredSoft.DynamicQuery.Core; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PoweredSoft.DynamicQuery.Cli +{ + public class PersonQueryInterceptor : IBeforeQueryAlteredInterceptor + { + public IQueryable InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable queryable) => queryable.Where(t => t.FirstName == "David"); + } + + public class Person + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } + + class Program + { + static void Main(string[] args) + { + Play1(); + + + } + + private static void Play1() + { + var list = new List() + { + new Person{ Id = 1, FirstName = "David", LastName = "Lebee "}, + new Person{ Id = 2, FirstName = "Michaela", LastName = "Lebee "}, + new Person{ Id = 3, FirstName = "Zohra", LastName = "Lebee "}, + new Person{ Id = 4, FirstName = "Eric", LastName = "Vickar "}, + new Person{ Id = 5, FirstName = "Susan", LastName = "Vickar "}, + }; + + var queryable = list.AsQueryable(); + + var qb = new QueryBuilder(); + qb.AddInterceptor(new PersonQueryInterceptor()); + qb.Execute(queryable, null); + } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/AggregateType.cs b/PoweredSoft.DynamicQuery.Core/AggregateType.cs new file mode 100644 index 0000000..fac51c7 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/AggregateType.cs @@ -0,0 +1,11 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public enum AggregateType + { + Count, + Sum, + Avg, + Max, + Min + } +} \ No newline at end of file diff --git a/PoweredSoft.DynamicQuery.Core/FilterType.cs b/PoweredSoft.DynamicQuery.Core/FilterType.cs new file mode 100644 index 0000000..38267a8 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/FilterType.cs @@ -0,0 +1,11 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public enum FilterType + { + Equals, + Contains, + StartsWith, + EndsWith, + Composite + } +} diff --git a/PoweredSoft.DynamicQuery.Core/IAggregate.cs b/PoweredSoft.DynamicQuery.Core/IAggregate.cs new file mode 100644 index 0000000..70bcf9c --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/IAggregate.cs @@ -0,0 +1,8 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public interface IAggregate + { + string Path { get; set; } + AggregateType Type { get; set; } + } +} \ No newline at end of file diff --git a/PoweredSoft.DynamicQuery.Core/ICompositeFilter.cs b/PoweredSoft.DynamicQuery.Core/ICompositeFilter.cs new file mode 100644 index 0000000..be4b772 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/ICompositeFilter.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace PoweredSoft.DynamicQuery.Core +{ + public interface ICompositeFilter : IFilter + { + List Filters { get; set; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/IFilter.cs b/PoweredSoft.DynamicQuery.Core/IFilter.cs new file mode 100644 index 0000000..bdeaed6 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/IFilter.cs @@ -0,0 +1,8 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public interface IFilter + { + bool? And { get; set; } + FilterType Type { get; set; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/IGroup.cs b/PoweredSoft.DynamicQuery.Core/IGroup.cs new file mode 100644 index 0000000..f1e93e6 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/IGroup.cs @@ -0,0 +1,8 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public interface IGroup + { + string Path { get; set; } + bool? Ascending { get; set; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/IQueryBuilder.cs b/PoweredSoft.DynamicQuery.Core/IQueryBuilder.cs new file mode 100644 index 0000000..104ef9b --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/IQueryBuilder.cs @@ -0,0 +1,55 @@ +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 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 : IQueryInterceptor + { + IQueryable InterceptQueryBeforeAltered(IQueryCriteria criteria, IQueryable queryable); + } + + public interface IFilterInteceptor : IQueryInterceptor + { + IEnumerable InterceptFilter(IFilter filter); + } + + public interface IGroupingInteceptor : IQueryInterceptor + { + IGroup InterceptGroup(IGroup group); + } + + public interface ISortInteceptor : IQueryInterceptor + { + IEnumerable InterceptSort(ISort sort); + } + + public interface IBeforeQueryExecuteInterceptor : IQueryInterceptor + { + IQueryable InterceptBeforeQuery(IQueryCriteria criteria, IQueryable queryable); + } + + public interface IBeforeQueryExecuteInterceptor : IQueryInterceptor + { + IQueryable InterceptBeforeQuery(IQueryCriteria criteria, IQueryable queryable); + } +} diff --git a/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs b/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs new file mode 100644 index 0000000..6184d15 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PoweredSoft.DynamicQuery.Core +{ + public interface IQueryCriteria + { + int? Page { get; set; } + int? PageSize { get; set; } + List Sorts { get; set; } + List Filters { get; set; } + List Groups { get; set; } + List Aggregates { get; set; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/IQueryResult.cs b/PoweredSoft.DynamicQuery.Core/IQueryResult.cs new file mode 100644 index 0000000..5fda81f --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/IQueryResult.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PoweredSoft.DynamicQuery.Core +{ + public interface IAggregateResult + { + string Path { get; set; } + AggregateType Type { get; set; } + object Value { get; set; } + } + + public interface IQueryResult + { + long Count { get; } + List Aggregates { get; } + } + + public interface IQueryResultSimple : IQueryResult + { + List Data { get; } + } + + public interface IQueryResultGrouped : IQueryResult + { + List Data { get; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/ISimpleFilter.cs b/PoweredSoft.DynamicQuery.Core/ISimpleFilter.cs new file mode 100644 index 0000000..26a7b1a --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/ISimpleFilter.cs @@ -0,0 +1,8 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public interface ISimpleFilter : IFilter + { + string Path { get; set; } + object Value { get; set; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/ISort.cs b/PoweredSoft.DynamicQuery.Core/ISort.cs new file mode 100644 index 0000000..2e5c9ff --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/ISort.cs @@ -0,0 +1,8 @@ +namespace PoweredSoft.DynamicQuery.Core +{ + public interface ISort + { + string Path { get; set; } + bool? Ascending { get; set; } + } +} diff --git a/PoweredSoft.DynamicQuery.Core/PoweredSoft.DynamicQuery.Core.csproj b/PoweredSoft.DynamicQuery.Core/PoweredSoft.DynamicQuery.Core.csproj new file mode 100644 index 0000000..9f5c4f4 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Core/PoweredSoft.DynamicQuery.Core.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/PoweredSoft.DynamicQuery/PoweredSoft.DynamicQuery.csproj b/PoweredSoft.DynamicQuery/PoweredSoft.DynamicQuery.csproj new file mode 100644 index 0000000..2f8f529 --- /dev/null +++ b/PoweredSoft.DynamicQuery/PoweredSoft.DynamicQuery.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/PoweredSoft.DynamicQuery/QueryBuilder.cs b/PoweredSoft.DynamicQuery/QueryBuilder.cs new file mode 100644 index 0000000..11d2b90 --- /dev/null +++ b/PoweredSoft.DynamicQuery/QueryBuilder.cs @@ -0,0 +1,72 @@ +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 Interceptors { get; } = new List(); + 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() + { + ApplySimpleBeforeAlterInterceptors(); + ApplyGenericBeforeAlterInterceptors(); + } + + private void ApplyInterceptorsAndCriteria() + { + var genericMethod = ApplyInterceptorsAndCriteriaMethod.MakeGenericMethod(QueryableUnderlyingType); + genericMethod.Invoke(this, null); + } + + protected virtual void ApplyGenericBeforeAlterInterceptors() + { + var interceptors = Interceptors.Where(t => t is IBeforeQueryAlteredInterceptor).Cast>().ToList(); + interceptors.ForEach(i => CurrentQueryable = i.InterceptQueryBeforeAltered(Criteria, (IQueryable)CurrentQueryable)); + } + + protected virtual void ApplySimpleBeforeAlterInterceptors() + { + var beforeAlterInterceptors = Interceptors.Where(t => t is IBeforeQueryAlteredInterceptor).Cast().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 ExecuteAsync(IQueryable queryable, IQueryCriteria criteria) + { + throw new NotImplementedException(); + } + } +}