dynamic query support.

This commit is contained in:
David Lebee
2021-02-02 19:01:29 -05:00
parent 8175dc5f3d
commit ca307194db
26 changed files with 698 additions and 12 deletions
@@ -0,0 +1,33 @@
using PoweredSoft.CQRS.Abstractions.Discovery;
using PoweredSoft.CQRS.Discovery;
using System;
using System.Collections.Generic;
using System.Text;
namespace PoweredSoft.CQRS.DynamicQuery.Discover
{
public class DynamicQueryMeta : QueryMeta
{
public DynamicQueryMeta(Type queryType, Type serviceType, Type queryResultType) : base(queryType, serviceType, queryResultType)
{
}
public Type SourceType => QueryType.GetGenericArguments()[0];
public Type DestinationType => QueryType.GetGenericArguments()[1];
public override string Category => "DynamicQuery";
public override string Name
{
get
{
if (NameAttribute != null)
return NameAttribute.Name;
var pluralizer = new Pluralize.NET.Pluralizer();
return pluralizer.Pluralize(DestinationType.Name);
}
}
public Type ParamsType { get; internal set; }
}
}
@@ -0,0 +1,85 @@
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> :
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)
{
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;
}
public async Task<IQueryExecutionResult<TDestination>> HandleAsync(IDynamicQuery<TSource, TDestination> query, CancellationToken cancellationToken = default)
{
return await ProcessQueryAsync(query, cancellationToken);
}
}
}
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Pluralize.NET" Version="1.0.2" />
<PackageReference Include="PoweredSoft.DynamicQuery" Version="2.1.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery.Abstractions\PoweredSoft.CQRS.DynamicQuery.Abstractions.csproj" />
<ProjectReference Include="..\PoweredSoft.CQRS\PoweredSoft.CQRS.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,54 @@
using Microsoft.Extensions.DependencyInjection;
using PoweredSoft.CQRS.Abstractions;
using PoweredSoft.CQRS.Abstractions.Discovery;
using PoweredSoft.CQRS.DynamicQuery.Abstractions;
using PoweredSoft.CQRS.DynamicQuery.Discover;
using PoweredSoft.DynamicQuery.Core;
using System;
using System.Collections.Generic;
using System.Text;
namespace PoweredSoft.CQRS.DynamicQuery
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddDynamicQuery<TSource, TDestination>(this IServiceCollection services)
where TSource : class
where TDestination : class
{
// add query handler.
services.AddTransient<PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination>, IQueryExecutionResult<TDestination>>, DynamicQueryHandler<TSource, TDestination>>();
// add for discovery purposes.
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
var resultType = typeof(IQueryExecutionResult<TDestination>);
var serviceType = typeof(DynamicQueryHandler<TSource, TDestination>);
var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType);
services.AddSingleton<IQueryMeta>(queryMeta);
return services;
}
public static IServiceCollection AddDynamicQueryWithParams<TSource, TDestination, TParams>(this IServiceCollection services)
where TSource : class
where TDestination : class
{
// add query handler.
services.AddTransient<PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination>, IQueryExecutionResult<TDestination>>, DynamicQueryHandler<TSource, TDestination>>();
// add for discovery purposes.
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
var resultType = typeof(IQueryExecutionResult<TDestination>);
var serviceType = typeof(DynamicQueryHandler<TSource, TDestination>);
var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType);
// params type.
queryMeta.ParamsType = typeof(TParams);
services.AddSingleton<IQueryMeta>(queryMeta);
return services;
}
}
}