more adjusted to support params.
This commit is contained in:
parent
ca307194db
commit
30e15e310c
@ -1,9 +1,4 @@
|
|||||||
using PoweredSoft.CQRS.DynamicQuery.Abstractions;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Demo.DynamicQueries
|
namespace Demo.DynamicQueries
|
||||||
{
|
{
|
||||||
@ -13,17 +8,8 @@ namespace Demo.DynamicQueries
|
|||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ContactQueryableProvider : IQueryableProvider<Contact>
|
public class SearchContactParams
|
||||||
{
|
{
|
||||||
public Task<IQueryable<Contact>> GetQueryableAsync(object query, CancellationToken cancelllationToken = default)
|
public string SearchDisplayName { get; set; }
|
||||||
{
|
|
||||||
var ret = new List<Contact>
|
|
||||||
{
|
|
||||||
new Contact { Id = 1, DisplayName = "David L"},
|
|
||||||
new Contact { Id = 2, DisplayName = "John Doe"}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Task.FromResult(ret.AsQueryable());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
Demo/DynamicQueries/ContactQueryableProvider.cs
Normal file
23
Demo/DynamicQueries/ContactQueryableProvider.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,7 @@ namespace Demo
|
|||||||
{
|
{
|
||||||
services.AddTransient<IQueryableProvider<Contact>, ContactQueryableProvider>();
|
services.AddTransient<IQueryableProvider<Contact>, ContactQueryableProvider>();
|
||||||
services.AddDynamicQuery<Contact, Contact>();
|
services.AddDynamicQuery<Contact, Contact>();
|
||||||
|
services.AddDynamicQueryWithParams<Contact, Contact, SearchContactParams>(name: "SearchContacts");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddCommands(IServiceCollection services)
|
private void AddCommands(IServiceCollection services)
|
||||||
|
@ -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
|
public interface IDynamicQuery
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -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 TSource : class
|
||||||
where TDestination : class
|
where TDestination : class
|
||||||
where TParams : class
|
where TParams : class
|
||||||
|
@ -33,7 +33,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore.Mvc
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IQueryExecutionResult<TDestination>> HandleAsync(
|
public async Task<IQueryExecutionResult<TDestination>> HandleAsync(
|
||||||
[FromBody] DynamicQuery<TSource, TDestination, TParams> query,
|
[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);
|
var result = await queryHandler.HandleAsync(query, HttpContext.RequestAborted);
|
||||||
|
@ -20,8 +20,8 @@ namespace PoweredSoft.CQRS.DynamicQuery.Discover
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (NameAttribute != null)
|
if (OverridableName != null)
|
||||||
return NameAttribute.Name;
|
return OverridableName;
|
||||||
|
|
||||||
var pluralizer = new Pluralize.NET.Pluralizer();
|
var pluralizer = new Pluralize.NET.Pluralizer();
|
||||||
return pluralizer.Pluralize(DestinationType.Name);
|
return pluralizer.Pluralize(DestinationType.Name);
|
||||||
@ -29,5 +29,6 @@ namespace PoweredSoft.CQRS.DynamicQuery.Discover
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Type ParamsType { get; internal set; }
|
public Type ParamsType { get; internal set; }
|
||||||
|
public string OverridableName { get; internal set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,85 +1,41 @@
|
|||||||
using PoweredSoft.CQRS.DynamicQuery.Abstractions;
|
using PoweredSoft.CQRS.DynamicQuery.Abstractions;
|
||||||
using PoweredSoft.DynamicQuery;
|
|
||||||
using PoweredSoft.DynamicQuery.Core;
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PoweredSoft.CQRS.DynamicQuery
|
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>>
|
PoweredSoft.CQRS.Abstractions.IQueryHandler<IDynamicQuery<TSource, TDestination>, IQueryExecutionResult<TDestination>>
|
||||||
where TSource : class
|
where TSource : class
|
||||||
where TDestination : class
|
where TDestination : class
|
||||||
|
|
||||||
{
|
{
|
||||||
private readonly IQueryHandlerAsync queryHandlerAsync;
|
public DynamicQueryHandler(IQueryHandlerAsync queryHandlerAsync, IEnumerable<IQueryableProvider<TSource>> queryableProviders) : base(queryHandlerAsync, queryableProviders)
|
||||||
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)
|
public Task<IQueryExecutionResult<TDestination>> HandleAsync(IDynamicQuery<TSource, TDestination> query, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (this.queryableProviders.Any())
|
return ProcessQueryAsync(query, cancellationToken);
|
||||||
return queryableProviders.ElementAt(0).GetQueryableAsync(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();
|
return this.ProcessQueryAsync(query, cancellationToken);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
78
PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs
Normal file
78
PoweredSoft.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ namespace PoweredSoft.CQRS.DynamicQuery
|
|||||||
{
|
{
|
||||||
public static class ServiceCollectionExtensions
|
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 TSource : class
|
||||||
where TDestination : class
|
where TDestination : class
|
||||||
{
|
{
|
||||||
@ -23,28 +23,35 @@ namespace PoweredSoft.CQRS.DynamicQuery
|
|||||||
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
|
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
|
||||||
var resultType = typeof(IQueryExecutionResult<TDestination>);
|
var resultType = typeof(IQueryExecutionResult<TDestination>);
|
||||||
var serviceType = typeof(DynamicQueryHandler<TSource, 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);
|
services.AddSingleton<IQueryMeta>(queryMeta);
|
||||||
|
|
||||||
return services;
|
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 TSource : class
|
||||||
where TDestination : class
|
where TDestination : class
|
||||||
|
where TParams : class
|
||||||
{
|
{
|
||||||
// add query handler.
|
// 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.
|
// add for discovery purposes.
|
||||||
var queryType = typeof(IDynamicQuery<TSource, TDestination>);
|
var queryType = typeof(IDynamicQuery<TSource, TDestination, TParams>);
|
||||||
var resultType = typeof(IQueryExecutionResult<TDestination>);
|
var resultType = typeof(IQueryExecutionResult<TDestination>);
|
||||||
var serviceType = typeof(DynamicQueryHandler<TSource, TDestination>);
|
var serviceType = typeof(DynamicQueryHandler<TSource, TDestination>);
|
||||||
var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType);
|
var queryMeta = new DynamicQueryMeta(queryType, serviceType, resultType)
|
||||||
|
{
|
||||||
|
|
||||||
// params type.
|
// params type.
|
||||||
queryMeta.ParamsType = typeof(TParams);
|
ParamsType = typeof(TParams),
|
||||||
|
OverridableName = name
|
||||||
|
};
|
||||||
|
|
||||||
services.AddSingleton<IQueryMeta>(queryMeta);
|
services.AddSingleton<IQueryMeta>(queryMeta);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user