using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using OpenHarbor.CQRS.DynamicQuery.Abstractions; using PoweredSoft.DynamicQuery; using PoweredSoft.DynamicQuery.Core; namespace OpenHarbor.CQRS.DynamicQuery; public abstract class DynamicQueryHandlerBase where TSource : class where TDestination : class { private readonly IQueryHandlerAsync _queryHandlerAsync; private readonly IEnumerable> _queryableProviders; private readonly IEnumerable> _alterQueryableServices; private readonly IEnumerable> _dynamicQueryInterceptorProviders; private readonly IServiceProvider _serviceProvider; public DynamicQueryHandlerBase(IQueryHandlerAsync queryHandlerAsync, IEnumerable> queryableProviders, IEnumerable> alterQueryableServices, IEnumerable> dynamicQueryInterceptorProviders, IServiceProvider serviceProvider) { _queryHandlerAsync = queryHandlerAsync; _queryableProviders = queryableProviders; _alterQueryableServices = alterQueryableServices; _dynamicQueryInterceptorProviders = dynamicQueryInterceptorProviders; _serviceProvider = serviceProvider; } protected virtual Task> GetQueryableAsync(IDynamicQuery query, CancellationToken cancellationToken = default) { if (_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() { var types = _dynamicQueryInterceptorProviders.SelectMany(t => t.GetInterceptorsTypes()).Distinct(); foreach (var type in types) yield return _serviceProvider.GetService(type) as IQueryInterceptor; } 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 = 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 async Task> AlterSourceAsync(IQueryable source, IDynamicQuery query, CancellationToken cancellationToken) { foreach (var t in _alterQueryableServices) source = await t.AlterQueryableAsync(source, query, cancellationToken); return 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; } }