more adjusted to support params.

This commit is contained in:
David Lebee 2021-02-02 19:32:39 -05:00
parent ca307194db
commit 30e15e310c
10 changed files with 151 additions and 91 deletions

View File

@ -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<Contact>
public class SearchContactParams
{
public Task<IQueryable<Contact>> GetQueryableAsync(object query, CancellationToken cancelllationToken = default)
{
var ret = new List<Contact>
{
new Contact { Id = 1, DisplayName = "David L"},
new Contact { Id = 2, DisplayName = "John Doe"}
};
return Task.FromResult(ret.AsQueryable());
}
public string SearchDisplayName { get; set; }
}
}

View File

@ -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<Contact>
{
public Task<IQueryable<Contact>> GetQueryableAsync(object query, CancellationToken cancelllationToken = default)
{
var source = new List<Contact>
{
new Contact { Id = 1, DisplayName = "David L"},
new Contact { Id = 2, DisplayName = "John Doe"}
};
var ret = source.AsQueryable();
return Task.FromResult(ret);
}
}
}

View File

@ -63,6 +63,7 @@ namespace Demo
{
services.AddTransient<IQueryableProvider<Contact>, ContactQueryableProvider>();
services.AddDynamicQuery<Contact, Contact>();
services.AddDynamicQueryWithParams<Contact, Contact, SearchContactParams>(name: "SearchContacts");
}
private void AddCommands(IServiceCollection services)

View File

@ -12,6 +12,14 @@ namespace PoweredSoft.CQRS.DynamicQuery.Abstractions
}
public interface IDynamicQuery<TSource, TDestination, TParams> : IDynamicQuery<TSource, TDestination>, IDynamicQueryParams<TParams>
where TSource : class
where TDestination : class
where TParams : class
{
}
public interface IDynamicQuery
{

View File

@ -15,7 +15,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore
}
public class DynamicQuery<TSource, TDestination, TParams> : DynamicQuery, IDynamicQuery<TSource, TDestination>, IDynamicQueryParams<TParams>
public class DynamicQuery<TSource, TDestination, TParams> : DynamicQuery, IDynamicQuery<TSource, TDestination, TParams>
where TSource : class
where TDestination : class
where TParams : class

View File

@ -33,7 +33,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore.Mvc
[HttpPost]
public async Task<IQueryExecutionResult<TDestination>> HandleAsync(
[FromBody] DynamicQuery<TSource, TDestination, TParams> query,
[FromServices] PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination>, IQueryExecutionResult<TDestination>> queryHandler
[FromServices] PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination, TParams>, IQueryExecutionResult<TDestination>> queryHandler
)
{
var result = await queryHandler.HandleAsync(query, HttpContext.RequestAborted);

View File

@ -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; }
}
}

View File

@ -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<TSource, TDestination> :
public class DynamicQueryHandler<TSource, TDestination>
: DynamicQueryHandlerBase<TSource, TDestination>,
PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination>, IQueryExecutionResult<TDestination>>
where TSource : class
where TDestination : class
{
private readonly IQueryHandlerAsync queryHandlerAsync;
private readonly IEnumerable<IQueryableProvider<TSource>> queryableProviders;
public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync,
IEnumerable<IQueryableProvider<TSource>> queryableProviders)
public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync, IEnumerable<IQueryableProvider<TSource>> queryableProviders) : base(queryHandlerAsync, queryableProviders)
{
this.queryHandlerAsync = queryHandlerAsync;
this.queryableProviders = queryableProviders;
}
protected virtual Task<IQueryable<TSource>> GetQueryableAsync(IDynamicQuery query, CancellationToken cancellationToken = default)
public Task<IQueryExecutionResult<TDestination>> HandleAsync(IDynamicQuery<TSource, TDestination> 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<TSource> for {typeof(TSource).Name}");
public class DynamicQueryHandler<TSource, TDestination, TParams>
: DynamicQueryHandlerBase<TSource, TDestination>,
PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination, TParams>, IQueryExecutionResult<TDestination>>
where TSource : class
where TDestination : class
where TParams : class
{
public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync, IEnumerable<IQueryableProvider<TSource>> queryableProviders) : base(queryHandlerAsync, queryableProviders)
{
}
public virtual IQueryExecutionOptions GetQueryExecutionOptions(IQueryable<TSource> source, IDynamicQuery query)
public Task<IQueryExecutionResult<TDestination>> HandleAsync(IDynamicQuery<TSource, TDestination, TParams> query, CancellationToken cancellationToken = default)
{
return new QueryExecutionOptions();
}
public virtual IEnumerable<IQueryInterceptor> GetInterceptors()
{
return Enumerable.Empty<IQueryInterceptor>();
}
protected async Task<IQueryExecutionResult<TDestination>> 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<TSource, TDestination>(source, criteria, options, cancellationToken);
return result;
}
protected virtual Task<IQueryable<TSource>> AlterSourceAsync(IQueryable<TSource> 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<IFilter>(),
Sorts = query?.GetSorts() ?? new List<ISort>(),
Groups = query.GetGroups() ?? new List<IGroup>(),
Aggregates = query.GetAggregates() ?? new List<IAggregate>()
};
return criteria;
}
public async Task<IQueryExecutionResult<TDestination>> HandleAsync(IDynamicQuery<TSource, TDestination> query, CancellationToken cancellationToken = default)
{
return await ProcessQueryAsync(query, cancellationToken);
return this.ProcessQueryAsync(query, cancellationToken);
}
}
}

View File

@ -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<TSource, TDestination>
where TSource : class
where TDestination : class
{
private readonly IQueryHandlerAsync queryHandlerAsync;
private readonly IEnumerable<IQueryableProvider<TSource>> queryableProviders;
public DynamicQueryHandlerBase(IQueryHandlerAsync queryHandlerAsync,
IEnumerable<IQueryableProvider<TSource>> queryableProviders)
{
this.queryHandlerAsync = queryHandlerAsync;
this.queryableProviders = queryableProviders;
}
protected virtual Task<IQueryable<TSource>> 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<TSource> for {typeof(TSource).Name}");
}
public virtual IQueryExecutionOptions GetQueryExecutionOptions(IQueryable<TSource> source, IDynamicQuery query)
{
return new QueryExecutionOptions();
}
public virtual IEnumerable<IQueryInterceptor> GetInterceptors()
{
return Enumerable.Empty<IQueryInterceptor>();
}
protected async Task<IQueryExecutionResult<TDestination>> 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<TSource, TDestination>(source, criteria, options, cancellationToken);
return result;
}
protected virtual Task<IQueryable<TSource>> AlterSourceAsync(IQueryable<TSource> 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<IFilter>(),
Sorts = query?.GetSorts() ?? new List<ISort>(),
Groups = query.GetGroups() ?? new List<IGroup>(),
Aggregates = query.GetAggregates() ?? new List<IAggregate>()
};
return criteria;
}
}
}

View File

@ -12,7 +12,7 @@ namespace PoweredSoft.CQRS.DynamicQuery
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddDynamicQuery<TSource, TDestination>(this IServiceCollection services)
public static IServiceCollection AddDynamicQuery<TSource, TDestination>(this IServiceCollection services, string name = null)
where TSource : class
where TDestination : class
{
@ -23,28 +23,35 @@ namespace PoweredSoft.CQRS.DynamicQuery
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
var resultType = typeof(IQueryExecutionResult<TDestination>);
var serviceType = typeof(DynamicQueryHandler<TSource, TDestination>);
var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType);
var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType)
{
OverridableName = name
};
services.AddSingleton<IQueryMeta>(queryMeta);
return services;
}
public static IServiceCollection AddDynamicQueryWithParams<TSource, TDestination, TParams>(this IServiceCollection services)
public static IServiceCollection AddDynamicQueryWithParams<TSource, TDestination, TParams>(this IServiceCollection services, string name = null)
where TSource : class
where TDestination : class
where TParams : class
{
// add query handler.
services.AddTransient<PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination>, IQueryExecutionResult<TDestination>>, DynamicQueryHandler<TSource, TDestination>>();
services.AddTransient<PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination, TParams>, IQueryExecutionResult<TDestination>>, DynamicQueryHandler<TSource, TDestination, TParams>>();
// add for discovery purposes.
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
var queryType = typeof(IDynamicQuery<TSource, TDestination, TParams>);
var resultType = typeof(IQueryExecutionResult<TDestination>);
var serviceType = typeof(DynamicQueryHandler<TSource, TDestination>);
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<IQueryMeta>(queryMeta);