From 30e15e310cab17b5c7e40bb0dbc9d796fc7501cc Mon Sep 17 00:00:00 2001 From: David Lebee Date: Tue, 2 Feb 2021 19:32:39 -0500 Subject: [PATCH] more adjusted to support params. --- Demo/DynamicQueries/Contact.cs | 20 +---- .../ContactQueryableProvider.cs | 23 ++++++ Demo/Startup.cs | 1 + .../IDynamicQuery.cs | 8 ++ .../DynamicQuery.cs | 2 +- .../Mvc/DynamicQueryController.cs | 2 +- .../Discover/DynamicQueryMeta.cs | 5 +- .../DynamicQueryHandler.cs | 80 +++++-------------- .../DynamicQueryHandlerBase.cs | 78 ++++++++++++++++++ .../ServiceCollectionExtensions.cs | 23 ++++-- 10 files changed, 151 insertions(+), 91 deletions(-) create mode 100644 Demo/DynamicQueries/ContactQueryableProvider.cs create mode 100644 PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs diff --git a/Demo/DynamicQueries/Contact.cs b/Demo/DynamicQueries/Contact.cs index 0ef525b..ced3f15 100644 --- a/Demo/DynamicQueries/Contact.cs +++ b/Demo/DynamicQueries/Contact.cs @@ -1,9 +1,4 @@ -using PoweredSoft.CQRS.DynamicQuery.Abstractions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using System; namespace Demo.DynamicQueries { @@ -13,17 +8,8 @@ namespace Demo.DynamicQueries public string DisplayName { get; set; } } - public class ContactQueryableProvider : IQueryableProvider + public class SearchContactParams { - public Task> GetQueryableAsync(object query, CancellationToken cancelllationToken = default) - { - var ret = new List - { - new Contact { Id = 1, DisplayName = "David L"}, - new Contact { Id = 2, DisplayName = "John Doe"} - }; - - return Task.FromResult(ret.AsQueryable()); - } + public string SearchDisplayName { get; set; } } } diff --git a/Demo/DynamicQueries/ContactQueryableProvider.cs b/Demo/DynamicQueries/ContactQueryableProvider.cs new file mode 100644 index 0000000..1947870 --- /dev/null +++ b/Demo/DynamicQueries/ContactQueryableProvider.cs @@ -0,0 +1,23 @@ +using PoweredSoft.CQRS.DynamicQuery.Abstractions; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Demo.DynamicQueries +{ + public class ContactQueryableProvider : IQueryableProvider + { + public Task> GetQueryableAsync(object query, CancellationToken cancelllationToken = default) + { + var source = new List + { + new Contact { Id = 1, DisplayName = "David L"}, + new Contact { Id = 2, DisplayName = "John Doe"} + }; + + var ret = source.AsQueryable(); + return Task.FromResult(ret); + } + } +} diff --git a/Demo/Startup.cs b/Demo/Startup.cs index 8e49e83..a5c290e 100644 --- a/Demo/Startup.cs +++ b/Demo/Startup.cs @@ -63,6 +63,7 @@ namespace Demo { services.AddTransient, ContactQueryableProvider>(); services.AddDynamicQuery(); + services.AddDynamicQueryWithParams(name: "SearchContacts"); } private void AddCommands(IServiceCollection services) diff --git a/PoweredSoft.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs b/PoweredSoft.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs index f5ee4c3..0780e60 100644 --- a/PoweredSoft.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs +++ b/PoweredSoft.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs @@ -12,6 +12,14 @@ namespace PoweredSoft.CQRS.DynamicQuery.Abstractions } + public interface IDynamicQuery : IDynamicQuery, IDynamicQueryParams + where TSource : class + where TDestination : class + where TParams : class + { + + } + public interface IDynamicQuery { diff --git a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/DynamicQuery.cs b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/DynamicQuery.cs index 880f79e..b9e2c83 100644 --- a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/DynamicQuery.cs +++ b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/DynamicQuery.cs @@ -15,7 +15,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore } - public class DynamicQuery : DynamicQuery, IDynamicQuery, IDynamicQueryParams + public class DynamicQuery : DynamicQuery, IDynamicQuery where TSource : class where TDestination : class where TParams : class diff --git a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs index 68e593c..e4ac69d 100644 --- a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs +++ b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs @@ -33,7 +33,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore.Mvc [HttpPost] public async Task> HandleAsync( [FromBody] DynamicQuery query, - [FromServices] PoweredSoft.CQRS.Abstractions.IQueryHandler, IQueryExecutionResult> queryHandler + [FromServices] PoweredSoft.CQRS.Abstractions.IQueryHandler, IQueryExecutionResult> queryHandler ) { var result = await queryHandler.HandleAsync(query, HttpContext.RequestAborted); diff --git a/PoweredSoft.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs b/PoweredSoft.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs index 794d6cc..a693c60 100644 --- a/PoweredSoft.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs +++ b/PoweredSoft.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs @@ -20,8 +20,8 @@ namespace PoweredSoft.CQRS.DynamicQuery.Discover { get { - if (NameAttribute != null) - return NameAttribute.Name; + if (OverridableName != null) + return OverridableName; var pluralizer = new Pluralize.NET.Pluralizer(); return pluralizer.Pluralize(DestinationType.Name); @@ -29,5 +29,6 @@ namespace PoweredSoft.CQRS.DynamicQuery.Discover } public Type ParamsType { get; internal set; } + public string OverridableName { get; internal set; } } } diff --git a/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandler.cs b/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandler.cs index ba24d31..9c38351 100644 --- a/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandler.cs +++ b/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandler.cs @@ -1,85 +1,41 @@ using PoweredSoft.CQRS.DynamicQuery.Abstractions; -using PoweredSoft.DynamicQuery; using PoweredSoft.DynamicQuery.Core; -using System; using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; namespace PoweredSoft.CQRS.DynamicQuery { - public class DynamicQueryHandler : + public class DynamicQueryHandler + : DynamicQueryHandlerBase, PoweredSoft.CQRS.Abstractions.IQueryHandler, IQueryExecutionResult> where TSource : class where TDestination : class - { - private readonly IQueryHandlerAsync queryHandlerAsync; - private readonly IEnumerable> queryableProviders; - - public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync, - IEnumerable> queryableProviders) + public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync, IEnumerable> queryableProviders) : base(queryHandlerAsync, queryableProviders) { - this.queryHandlerAsync = queryHandlerAsync; - this.queryableProviders = queryableProviders; } - protected virtual Task> GetQueryableAsync(IDynamicQuery query, CancellationToken cancellationToken = default) + public Task> HandleAsync(IDynamicQuery query, CancellationToken cancellationToken = default) { - if (this.queryableProviders.Any()) - return queryableProviders.ElementAt(0).GetQueryableAsync(query, cancellationToken); + return ProcessQueryAsync(query, cancellationToken); + } + } - throw new Exception($"You must provide a QueryableProvider for {typeof(TSource).Name}"); + public class DynamicQueryHandler + : DynamicQueryHandlerBase, + PoweredSoft.CQRS.Abstractions.IQueryHandler, IQueryExecutionResult> + where TSource : class + where TDestination : class + where TParams : class + { + public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync, IEnumerable> queryableProviders) : base(queryHandlerAsync, queryableProviders) + { } - public virtual IQueryExecutionOptions GetQueryExecutionOptions(IQueryable source, IDynamicQuery query) + public Task> HandleAsync(IDynamicQuery query, CancellationToken cancellationToken = default) { - return new QueryExecutionOptions(); - } - - public virtual IEnumerable GetInterceptors() - { - return Enumerable.Empty(); - } - - protected async Task> ProcessQueryAsync(IDynamicQuery query, CancellationToken cancellationToken = default) - { - var source = await GetQueryableAsync(query, cancellationToken); - source = await AlterSourceAsync(source, query, cancellationToken); - var options = GetQueryExecutionOptions(source, query); - var interceptors = this.GetInterceptors(); - - foreach (var interceptor in interceptors) - queryHandlerAsync.AddInterceptor(interceptor); - - var criteria = CreateCriteriaFromQuery(query); - var result = await queryHandlerAsync.ExecuteAsync(source, criteria, options, cancellationToken); - return result; - } - - protected virtual Task> AlterSourceAsync(IQueryable source, IDynamicQuery query, CancellationToken cancellationToken) - { - return Task.FromResult(source); - } - - protected virtual IQueryCriteria CreateCriteriaFromQuery(IDynamicQuery query) - { - var criteria = new QueryCriteria - { - Page = query?.GetPage(), - PageSize = query?.GetPageSize(), - Filters = query?.GetFilters() ?? new List(), - Sorts = query?.GetSorts() ?? new List(), - Groups = query.GetGroups() ?? new List(), - Aggregates = query.GetAggregates() ?? new List() - }; - return criteria; - } - - public async Task> HandleAsync(IDynamicQuery query, CancellationToken cancellationToken = default) - { - return await ProcessQueryAsync(query, cancellationToken); + return this.ProcessQueryAsync(query, cancellationToken); } } } diff --git a/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs b/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs new file mode 100644 index 0000000..07c1581 --- /dev/null +++ b/PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs @@ -0,0 +1,78 @@ +using PoweredSoft.CQRS.DynamicQuery.Abstractions; +using PoweredSoft.DynamicQuery; +using PoweredSoft.DynamicQuery.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace PoweredSoft.CQRS.DynamicQuery +{ + public abstract class DynamicQueryHandlerBase + where TSource : class + where TDestination : class + { + private readonly IQueryHandlerAsync queryHandlerAsync; + private readonly IEnumerable> queryableProviders; + + public DynamicQueryHandlerBase(IQueryHandlerAsync queryHandlerAsync, + IEnumerable> queryableProviders) + { + this.queryHandlerAsync = queryHandlerAsync; + this.queryableProviders = queryableProviders; + } + + protected virtual Task> GetQueryableAsync(IDynamicQuery query, CancellationToken cancellationToken = default) + { + if (this.queryableProviders.Any()) + return queryableProviders.ElementAt(0).GetQueryableAsync(query, cancellationToken); + + throw new Exception($"You must provide a QueryableProvider for {typeof(TSource).Name}"); + } + + public virtual IQueryExecutionOptions GetQueryExecutionOptions(IQueryable source, IDynamicQuery query) + { + return new QueryExecutionOptions(); + } + + public virtual IEnumerable GetInterceptors() + { + return Enumerable.Empty(); + } + + protected async Task> ProcessQueryAsync(IDynamicQuery query, CancellationToken cancellationToken = default) + { + var source = await GetQueryableAsync(query, cancellationToken); + source = await AlterSourceAsync(source, query, cancellationToken); + var options = GetQueryExecutionOptions(source, query); + var interceptors = this.GetInterceptors(); + + foreach (var interceptor in interceptors) + queryHandlerAsync.AddInterceptor(interceptor); + + var criteria = CreateCriteriaFromQuery(query); + var result = await queryHandlerAsync.ExecuteAsync(source, criteria, options, cancellationToken); + return result; + } + + protected virtual Task> AlterSourceAsync(IQueryable source, IDynamicQuery query, CancellationToken cancellationToken) + { + return Task.FromResult(source); + } + + protected virtual IQueryCriteria CreateCriteriaFromQuery(IDynamicQuery query) + { + var criteria = new QueryCriteria + { + Page = query?.GetPage(), + PageSize = query?.GetPageSize(), + Filters = query?.GetFilters() ?? new List(), + Sorts = query?.GetSorts() ?? new List(), + Groups = query.GetGroups() ?? new List(), + Aggregates = query.GetAggregates() ?? new List() + }; + return criteria; + } + } +} diff --git a/PoweredSoft.CQRS.DynamicQuery/ServiceCollectionExtensions.cs b/PoweredSoft.CQRS.DynamicQuery/ServiceCollectionExtensions.cs index 382bf70..7554a4d 100644 --- a/PoweredSoft.CQRS.DynamicQuery/ServiceCollectionExtensions.cs +++ b/PoweredSoft.CQRS.DynamicQuery/ServiceCollectionExtensions.cs @@ -12,7 +12,7 @@ namespace PoweredSoft.CQRS.DynamicQuery { public static class ServiceCollectionExtensions { - public static IServiceCollection AddDynamicQuery(this IServiceCollection services) + public static IServiceCollection AddDynamicQuery(this IServiceCollection services, string name = null) where TSource : class where TDestination : class { @@ -23,28 +23,35 @@ namespace PoweredSoft.CQRS.DynamicQuery var queryType = typeof(IDynamicQuery); var resultType = typeof(IQueryExecutionResult); var serviceType = typeof(DynamicQueryHandler); - var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType); + var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType) + { + OverridableName = name + }; services.AddSingleton(queryMeta); return services; } - public static IServiceCollection AddDynamicQueryWithParams(this IServiceCollection services) + public static IServiceCollection AddDynamicQueryWithParams(this IServiceCollection services, string name = null) where TSource : class where TDestination : class + where TParams : class { // add query handler. - services.AddTransient, IQueryExecutionResult>, DynamicQueryHandler>(); + services.AddTransient, IQueryExecutionResult>, DynamicQueryHandler>(); // add for discovery purposes. - var queryType = typeof(IDynamicQuery); + var queryType = typeof(IDynamicQuery); var resultType = typeof(IQueryExecutionResult); var serviceType = typeof(DynamicQueryHandler); - var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType); + var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType) + { - // params type. - queryMeta.ParamsType = typeof(TParams); + // params type. + ParamsType = typeof(TParams), + OverridableName = name + }; services.AddSingleton(queryMeta);