Resolve Query Interceptor and queryable Interceptor provider :)

This commit is contained in:
David Lebee 2019-12-12 17:37:32 -06:00
parent 5be4b7e3ac
commit 6a49098836
22 changed files with 158 additions and 52 deletions

View File

@ -119,7 +119,7 @@ namespace PoweredSoft.DynamicQuery.Cli
new Aggregate { Path = "AgeStr", Type = AggregateType.Avg } new Aggregate { Path = "AgeStr", Type = AggregateType.Avg }
};; };;
var handler = new QueryHandler(); var handler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
handler.AddInterceptor(new PersonQueryInterceptor()); handler.AddInterceptor(new PersonQueryInterceptor());
var result = handler.Execute(queryable, criteria); var result = handler.Execute(queryable, criteria);

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -9,6 +10,7 @@ namespace PoweredSoft.DynamicQuery.Core
public interface IInterceptableQueryHandler public interface IInterceptableQueryHandler
{ {
void AddInterceptor(IQueryInterceptor interceptor); void AddInterceptor(IQueryInterceptor interceptor);
IReadOnlyList<IQueryInterceptor> ResolveInterceptors<TSource, TResult>(IQueryCriteria criteria, IQueryable<TSource> queryable);
} }
public interface IQueryHandler : IInterceptableQueryHandler public interface IQueryHandler : IInterceptableQueryHandler

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Linq;
namespace PoweredSoft.DynamicQuery.Core
{
public interface IQueryInterceptorProvider
{
IEnumerable<IQueryInterceptor> GetInterceptors<TSource, TResult>(IQueryCriteria queryCriteria, IQueryable<TSource> queryable);
}
}

View File

@ -38,7 +38,7 @@ namespace PoweredSoft.DynamicQuery.Test
Type = AggregateType.Avg, Type = AggregateType.Avg,
Path = "ItemPrice" Path = "ItemPrice"
}); });
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockAggregateInterceptor()); queryHandler.AddInterceptor(new MockAggregateInterceptor());
var result = queryHandler.Execute(ctx.Items, criteria); var result = queryHandler.Execute(ctx.Items, criteria);
Assert.Equal(expected.PriceAtTheTime, result.Aggregates.First().Value); Assert.Equal(expected.PriceAtTheTime, result.Aggregates.First().Value);

View File

@ -56,7 +56,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.OrderItems, criteria, new QueryExecutionOptions var result = queryHandler.Execute(ctx.OrderItems, criteria, new QueryExecutionOptions
{ {
GroupByInMemory = true GroupByInMemory = true
@ -122,7 +122,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var queryable = ctx.OrderItems.Include(t => t.Order); var queryable = ctx.OrderItems.Include(t => t.Order);
var result = queryHandler.Execute(queryable, criteria, new QueryExecutionOptions var result = queryHandler.Execute(queryable, criteria, new QueryExecutionOptions
{ {

View File

@ -27,7 +27,7 @@ namespace PoweredSoft.DynamicQuery.Test
// query handler that is empty should be the same as running to list. // query handler that is empty should be the same as running to list.
var aqf = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var aqf = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
var queryHandler = new QueryHandlerAsync(aqf); var queryHandler = new QueryHandlerAsync(aqf, Enumerable.Empty<IQueryInterceptorProvider>());
var result = await queryHandler.ExecuteAsync(queryable, criteria); var result = await queryHandler.ExecuteAsync(queryable, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -66,7 +66,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
var result = await queryHandler.ExecuteAsync(ctx.OrderItems.Include(t => t.Order.Customer), criteria, new QueryExecutionOptions var result = await queryHandler.ExecuteAsync(ctx.OrderItems.Include(t => t.Order.Customer), criteria, new QueryExecutionOptions
{ {
GroupByInMemory = true GroupByInMemory = true
@ -118,7 +118,7 @@ namespace PoweredSoft.DynamicQuery.Test
}; };
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
var result = await queryHandler.ExecuteAsync(ctx.Items, criteria); var result = await queryHandler.ExecuteAsync(ctx.Items, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -146,7 +146,7 @@ namespace PoweredSoft.DynamicQuery.Test
}; };
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
var result = await queryHandler.ExecuteAsync(ctx.Items, criteria); var result = await queryHandler.ExecuteAsync(ctx.Items, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -166,7 +166,7 @@ namespace PoweredSoft.DynamicQuery.Test
criteria.PageSize = 5; criteria.PageSize = 5;
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria); var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -205,7 +205,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockQueryExecutionOptionsInterceptor()); queryHandler.AddInterceptor(new MockQueryExecutionOptionsInterceptor());
var result = await queryHandler.ExecuteAsync(ctx.OrderItems.Include(t => t.Order.Customer), criteria); var result = await queryHandler.ExecuteAsync(ctx.OrderItems.Include(t => t.Order.Customer), criteria);

View File

@ -50,7 +50,7 @@ namespace PoweredSoft.DynamicQuery.Test
queryable = (IQueryable<Order>)interceptor.InterceptBeforeFiltering(criteria, queryable); queryable = (IQueryable<Order>)interceptor.InterceptBeforeFiltering(criteria, queryable);
// query handler should pass by the same interceptor. // query handler should pass by the same interceptor.
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
@ -75,7 +75,7 @@ namespace PoweredSoft.DynamicQuery.Test
queryable = interceptor.InterceptBeforeFiltering(criteria, queryable); queryable = interceptor.InterceptBeforeFiltering(criteria, queryable);
// query handler should pass by the same interceptor. // query handler should pass by the same interceptor.
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);

View File

@ -2,6 +2,7 @@
using PoweredSoft.DynamicQuery.Test.Mock; using PoweredSoft.DynamicQuery.Test.Mock;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using Xunit; using Xunit;
@ -77,7 +78,7 @@ namespace PoweredSoft.DynamicQuery.Test
MockContextFactory.SeedAndTestContextFor("QueryConvertInterceptorTests_NonGeneric", TestSeeders.SimpleSeedScenario, ctx => MockContextFactory.SeedAndTestContextFor("QueryConvertInterceptorTests_NonGeneric", TestSeeders.SimpleSeedScenario, ctx =>
{ {
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockQueryConvertInterceptor()); queryHandler.AddInterceptor(new MockQueryConvertInterceptor());
var result = queryHandler.Execute<Customer, CustomerModel>(ctx.Customers, criteria); var result = queryHandler.Execute<Customer, CustomerModel>(ctx.Customers, criteria);
Assert.All(result.Data, t => Assert.IsType<CustomerModel>(t)); Assert.All(result.Data, t => Assert.IsType<CustomerModel>(t));
@ -90,7 +91,7 @@ namespace PoweredSoft.DynamicQuery.Test
MockContextFactory.SeedAndTestContextFor("ConvertibleIntereceptorTests_Generic", TestSeeders.SimpleSeedScenario, ctx => MockContextFactory.SeedAndTestContextFor("ConvertibleIntereceptorTests_Generic", TestSeeders.SimpleSeedScenario, ctx =>
{ {
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockQueryConvertGenericInterceptor()); queryHandler.AddInterceptor(new MockQueryConvertGenericInterceptor());
var result = queryHandler.Execute<Customer, CustomerModel>(ctx.Customers, criteria); var result = queryHandler.Execute<Customer, CustomerModel>(ctx.Customers, criteria);
Assert.All(result.Data, t => Assert.IsType<CustomerModel>(t)); Assert.All(result.Data, t => Assert.IsType<CustomerModel>(t));
@ -103,7 +104,7 @@ namespace PoweredSoft.DynamicQuery.Test
MockContextFactory.SeedAndTestContextFor("ConvertibleIntereceptorTests_Generic2", TestSeeders.SimpleSeedScenario, ctx => MockContextFactory.SeedAndTestContextFor("ConvertibleIntereceptorTests_Generic2", TestSeeders.SimpleSeedScenario, ctx =>
{ {
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockQueryConvertGenericInterceptor2()); queryHandler.AddInterceptor(new MockQueryConvertGenericInterceptor2());
var result = queryHandler.Execute<Customer, CustomerModel>(ctx.Customers, criteria); var result = queryHandler.Execute<Customer, CustomerModel>(ctx.Customers, criteria);
Assert.All(result.Data, t => Assert.IsType<CustomerModel>(t)); Assert.All(result.Data, t => Assert.IsType<CustomerModel>(t));

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using PoweredSoft.DynamicQuery.Core;
using PoweredSoft.DynamicQuery.Test.Mock; using PoweredSoft.DynamicQuery.Test.Mock;
using Xunit; using Xunit;
@ -19,7 +20,7 @@ namespace PoweredSoft.DynamicQuery.Test
// query handler that is empty should be the same as running to list. // query handler that is empty should be the same as running to list.
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(queryable, criteria); var result = queryHandler.Execute(queryable, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -38,7 +39,7 @@ namespace PoweredSoft.DynamicQuery.Test
criteria.Page = 2; criteria.Page = 2;
criteria.PageSize = 5; criteria.PageSize = 5;
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.OrderItems, criteria); var result = queryHandler.Execute(ctx.OrderItems, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });

View File

@ -58,7 +58,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var query = new QueryHandler(); var query = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
query.AddInterceptor(new MockFilterInterceptorA()); query.AddInterceptor(new MockFilterInterceptorA());
var result = query.Execute(queryable, criteria); var result = query.Execute(queryable, criteria);
@ -83,7 +83,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var query = new QueryHandler(); var query = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
query.AddInterceptor(new MockFilterInterceptorAWithExtension()); query.AddInterceptor(new MockFilterInterceptorAWithExtension());
var result = query.Execute(queryable, criteria); var result = query.Execute(queryable, criteria);
@ -108,7 +108,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var query = new QueryHandler(); var query = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
query.AddInterceptor(new MockFilterInterceptorAWithExtension()); query.AddInterceptor(new MockFilterInterceptorAWithExtension());
var result = query.Execute(queryable, criteria); var result = query.Execute(queryable, criteria);
@ -133,7 +133,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var query = new QueryHandler(); var query = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
query.AddInterceptor(new MockFilterInterceptorA()); query.AddInterceptor(new MockFilterInterceptorA());
query.AddInterceptor(new MockFilterInterceptorB()); query.AddInterceptor(new MockFilterInterceptorB());
var result = query.Execute(queryable, criteria); var result = query.Execute(queryable, criteria);

View File

@ -32,7 +32,7 @@ namespace PoweredSoft.DynamicQuery.Test
Filters = new List<IFilter> { new MockIsChuckFilter() } Filters = new List<IFilter> { new MockIsChuckFilter() }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Customers, criteria); var result = queryHandler.Execute(ctx.Customers, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -58,7 +58,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Items, criteria); var result = queryHandler.Execute(ctx.Items, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -89,7 +89,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Customers, criteria); var result = queryHandler.Execute(ctx.Customers, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });
@ -125,7 +125,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Customers, criteria); var result = queryHandler.Execute(ctx.Customers, criteria);
Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
}); });

View File

@ -36,7 +36,7 @@ namespace PoweredSoft.DynamicQuery.Test
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
criteria.Groups.Add(new Group { Path = "CustomerFirstName" }); criteria.Groups.Add(new Group { Path = "CustomerFirstName" });
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockGroupInterceptor()); queryHandler.AddInterceptor(new MockGroupInterceptor());
var result = queryHandler.Execute(ctx.Orders.Include(t => t.Customer), criteria, new QueryExecutionOptions var result = queryHandler.Execute(ctx.Orders.Include(t => t.Customer), criteria, new QueryExecutionOptions
{ {
@ -52,7 +52,7 @@ namespace PoweredSoft.DynamicQuery.Test
[Fact] [Fact]
public void WithInterptorSimple() public void WithInterptorSimple()
{ {
MockContextFactory.SeedAndTestContextFor("GroupInterceptorTests_Simple", TestSeeders.SimpleSeedScenario, ctx => MockContextFactory.SeedAndTestContextFor("GroupInterceptorTests_WithInterptorSimple", TestSeeders.SimpleSeedScenario, ctx =>
{ {
var expected = ctx.Orders var expected = ctx.Orders
.OrderBy(t => t.Customer.FirstName) .OrderBy(t => t.Customer.FirstName)
@ -62,7 +62,7 @@ namespace PoweredSoft.DynamicQuery.Test
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
criteria.Groups.Add(new Group { Path = "CustomerFirstName" }); criteria.Groups.Add(new Group { Path = "CustomerFirstName" });
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockGroupInterceptor()); queryHandler.AddInterceptor(new MockGroupInterceptor());
queryHandler.AddInterceptor(new MockQueryExecutionOptionsInterceptor()); queryHandler.AddInterceptor(new MockQueryExecutionOptionsInterceptor());
var result = queryHandler.Execute(ctx.Orders.Include(t => t.Customer), criteria); var result = queryHandler.Execute(ctx.Orders.Include(t => t.Customer), criteria);

View File

@ -39,7 +39,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Orders, criteria, new QueryExecutionOptions var result = queryHandler.Execute(ctx.Orders, criteria, new QueryExecutionOptions
{ {
GroupByInMemory = true, GroupByInMemory = true,
@ -80,7 +80,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Tickets, criteria, new QueryExecutionOptions var result = queryHandler.Execute(ctx.Tickets, criteria, new QueryExecutionOptions
{ {
GroupByInMemory = true GroupByInMemory = true
@ -117,7 +117,7 @@ namespace PoweredSoft.DynamicQuery.Test
}; };
var interceptor = new InterceptorsWithGrouping(); var interceptor = new InterceptorsWithGrouping();
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute<Ticket, InterceptorWithGroupingFakeModel>(ctx.Tickets, criteria, new QueryExecutionOptions var result = queryHandler.Execute<Ticket, InterceptorWithGroupingFakeModel>(ctx.Tickets, criteria, new QueryExecutionOptions
{ {

View File

@ -51,7 +51,7 @@ namespace PoweredSoft.DynamicQuery.Test
queryable = (IQueryable<Order>)interceptor.InterceptIncludeStrategy(criteria, queryable); queryable = (IQueryable<Order>)interceptor.InterceptIncludeStrategy(criteria, queryable);
// query handler should pass by the same interceptor. // query handler should pass by the same interceptor.
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
@ -76,7 +76,7 @@ namespace PoweredSoft.DynamicQuery.Test
queryable = interceptor.InterceptIncludeStrategy(criteria, queryable); queryable = interceptor.InterceptIncludeStrategy(criteria, queryable);
// query handler should pass by the same interceptor. // query handler should pass by the same interceptor.
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);

View File

@ -51,7 +51,7 @@ namespace PoweredSoft.DynamicQuery.Test
queryable = (IQueryable<Order>)interceptor.InterceptNoSort(criteria, queryable); queryable = (IQueryable<Order>)interceptor.InterceptNoSort(criteria, queryable);
// query handler should pass by the same interceptor. // query handler should pass by the same interceptor.
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
@ -76,7 +76,7 @@ namespace PoweredSoft.DynamicQuery.Test
queryable = interceptor.InterceptNoSort(criteria, queryable); queryable = interceptor.InterceptNoSort(criteria, queryable);
// query handler should pass by the same interceptor. // query handler should pass by the same interceptor.
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(interceptor); queryHandler.AddInterceptor(interceptor);
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);

View File

@ -0,0 +1,44 @@
using PoweredSoft.DynamicQuery.Core;
using PoweredSoft.DynamicQuery.Test.Mock;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
namespace PoweredSoft.DynamicQuery.Test
{
public class QueryProviderTests
{
private class FakeInterceptor : IQueryInterceptor
{
}
private class QueryInterceptorProvider : IQueryInterceptorProvider
{
public IEnumerable<IQueryInterceptor> GetInterceptors<TSource, TResult>(IQueryCriteria queryCriteria, IQueryable<TSource> queryable)
{
yield return new FakeInterceptor();
yield return new FakeInterceptor();
}
}
[Fact]
public void Simple()
{
MockContextFactory.SeedAndTestContextFor("QueryProviderTests_Simple", TestSeeders.SimpleSeedScenario, ctx =>
{
// criteria
var criteria = new QueryCriteria();
var queryHandler = new QueryHandler(new List<IQueryInterceptorProvider>{
new QueryInterceptorProvider()
});
queryHandler.AddInterceptor(new FakeInterceptor());
var interceptors = queryHandler.ResolveInterceptors<Order, Order>(criteria, ctx.Orders);
Assert.Equal(1, interceptors.Count);
Assert.True(interceptors[0].GetType() == typeof(FakeInterceptor));
});
}
}
}

View File

@ -33,7 +33,7 @@ namespace PoweredSoft.DynamicQuery.Test
// criteria // criteria
var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
criteria.Sorts.Add(new Sort("CustomerFullName")); criteria.Sorts.Add(new Sort("CustomerFullName"));
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockSortInterceptor()); queryHandler.AddInterceptor(new MockSortInterceptor());
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
Assert.Equal(expected, result.Data); Assert.Equal(expected, result.Data);

View File

@ -27,7 +27,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
Assert.Equal(shouldResult, result.Data); Assert.Equal(shouldResult, result.Data);
}); });
@ -50,7 +50,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
Assert.Equal(shouldResult, result.Data); Assert.Equal(shouldResult, result.Data);
}); });
@ -83,7 +83,7 @@ namespace PoweredSoft.DynamicQuery.Test
} }
}; };
var queryHandler = new QueryHandler(); var queryHandler = new QueryHandler(Enumerable.Empty<IQueryInterceptorProvider>());
queryHandler.AddInterceptor(new MockSortInterceptor()); queryHandler.AddInterceptor(new MockSortInterceptor());
var result = queryHandler.Execute(ctx.Orders, criteria); var result = queryHandler.Execute(ctx.Orders, criteria);
Assert.Equal(shouldResult, result.Data); Assert.Equal(shouldResult, result.Data);

View File

@ -14,6 +14,10 @@ namespace PoweredSoft.DynamicQuery
{ {
public class QueryHandler : QueryHandlerBase, IQueryHandler public class QueryHandler : QueryHandlerBase, IQueryHandler
{ {
public QueryHandler(IEnumerable<IQueryInterceptorProvider> queryableInterceptorProviders) : base(queryableInterceptorProviders)
{
}
protected virtual IQueryExecutionResult<TRecord> FinalExecute<TSource, TRecord>() protected virtual IQueryExecutionResult<TRecord> FinalExecute<TSource, TRecord>()
{ {
CommonBeforeExecute<TSource>(); CommonBeforeExecute<TSource>();
@ -127,25 +131,25 @@ namespace PoweredSoft.DynamicQuery
public IQueryExecutionResult<TSource> Execute<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria) public IQueryExecutionResult<TSource> Execute<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria)
{ {
Reset(queryable, criteria, new QueryExecutionOptions()); Reset<TSource, TSource>(queryable, criteria, new QueryExecutionOptions());
return FinalExecute<TSource, TSource>(); return FinalExecute<TSource, TSource>();
} }
public IQueryExecutionResult<TRecord> Execute<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria) public IQueryExecutionResult<TRecord> Execute<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria)
{ {
Reset(queryable, criteria, new QueryExecutionOptions()); Reset<TSource, TRecord>(queryable, criteria, new QueryExecutionOptions());
return FinalExecute<TSource, TRecord>(); return FinalExecute<TSource, TRecord>();
} }
public IQueryExecutionResult<TSource> Execute<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options) public IQueryExecutionResult<TSource> Execute<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options)
{ {
Reset(queryable, criteria, options); Reset<TSource, TSource>(queryable, criteria, options);
return FinalExecute<TSource, TSource>(); return FinalExecute<TSource, TSource>();
} }
public IQueryExecutionResult<TRecord> Execute<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options) public IQueryExecutionResult<TRecord> Execute<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options)
{ {
Reset(queryable, criteria, options); Reset<TSource, TRecord>(queryable, criteria, options);
return FinalExecute<TSource, TRecord>(); return FinalExecute<TSource, TRecord>();
} }
} }

View File

@ -15,7 +15,7 @@ namespace PoweredSoft.DynamicQuery
{ {
public IAsyncQueryableService AsyncQueryableService { get; } public IAsyncQueryableService AsyncQueryableService { get; }
public QueryHandlerAsync(IAsyncQueryableService asyncQueryableService) public QueryHandlerAsync(IAsyncQueryableService asyncQueryableService, IEnumerable<IQueryInterceptorProvider> queryInterceptorProviders) : base(queryInterceptorProviders)
{ {
AsyncQueryableService = asyncQueryableService; AsyncQueryableService = asyncQueryableService;
} }
@ -157,25 +157,25 @@ namespace PoweredSoft.DynamicQuery
public Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default) public Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default)
{ {
Reset(queryable, criteria, new QueryExecutionOptions()); Reset<TSource, TSource>(queryable, criteria, new QueryExecutionOptions());
return FinalExecuteAsync<TSource, TSource>(cancellationToken); return FinalExecuteAsync<TSource, TSource>(cancellationToken);
} }
public Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default) public Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default)
{ {
Reset(queryable, criteria, new QueryExecutionOptions()); Reset<TSource, TRecord>(queryable, criteria, new QueryExecutionOptions());
return FinalExecuteAsync<TSource, TRecord>(cancellationToken); return FinalExecuteAsync<TSource, TRecord>(cancellationToken);
} }
public Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options, CancellationToken cancellationToken = default) public Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options, CancellationToken cancellationToken = default)
{ {
Reset(queryable, criteria, options); Reset<TSource, TSource>(queryable, criteria, options);
return FinalExecuteAsync<TSource, TSource>(cancellationToken); return FinalExecuteAsync<TSource, TSource>(cancellationToken);
} }
public Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options, CancellationToken cancellationToken = default) public Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options, CancellationToken cancellationToken = default)
{ {
Reset(queryable, criteria, options); Reset<TSource, TRecord>(queryable, criteria, options);
return FinalExecuteAsync<TSource, TRecord>(cancellationToken); return FinalExecuteAsync<TSource, TRecord>(cancellationToken);
} }
} }

View File

@ -16,7 +16,9 @@ namespace PoweredSoft.DynamicQuery
{ {
public abstract class QueryHandlerBase : IInterceptableQueryHandler public abstract class QueryHandlerBase : IInterceptableQueryHandler
{ {
protected List<IQueryInterceptor> Interceptors { get; } = new List<IQueryInterceptor>(); private readonly IEnumerable<IQueryInterceptorProvider> queryableInterceptorProviders;
protected List<IQueryInterceptor> AddedInterceptors { get; } = new List<IQueryInterceptor>();
protected IQueryCriteria Criteria { get; set; } protected IQueryCriteria Criteria { get; set; }
protected IQueryable QueryableAtStart { get; private set; } protected IQueryable QueryableAtStart { get; private set; }
protected IQueryable CurrentQueryable { get; set; } protected IQueryable CurrentQueryable { get; set; }
@ -26,8 +28,21 @@ namespace PoweredSoft.DynamicQuery
protected bool HasGrouping => Criteria.Groups?.Any() == true; protected bool HasGrouping => Criteria.Groups?.Any() == true;
protected bool HasPaging => Criteria.PageSize.HasValue && Criteria.PageSize > 0; protected bool HasPaging => Criteria.PageSize.HasValue && Criteria.PageSize > 0;
protected virtual void Reset(IQueryable queryable, IQueryCriteria criteria, IQueryExecutionOptions options) protected IReadOnlyList<IQueryInterceptor> Interceptors { get; set; }
protected virtual void ResetInterceptors<TSource, TResult>(IQueryCriteria criteria, IQueryable<TSource> queryable)
{ {
Interceptors = ResolveInterceptors<TSource, TResult>(criteria, queryable);
}
public QueryHandlerBase(IEnumerable<IQueryInterceptorProvider> queryableInterceptorProviders)
{
this.queryableInterceptorProviders = queryableInterceptorProviders;
}
protected virtual void Reset<TSource, TResult>(IQueryable<TSource> queryable, IQueryCriteria criteria, IQueryExecutionOptions options)
{
ResetInterceptors<TSource, TResult>(criteria, queryable);
Criteria = criteria ?? throw new ArgumentNullException("criteria"); Criteria = criteria ?? throw new ArgumentNullException("criteria");
QueryableAtStart = queryable ?? throw new ArgumentNullException("queryable"); QueryableAtStart = queryable ?? throw new ArgumentNullException("queryable");
CurrentQueryable = QueryableAtStart; CurrentQueryable = QueryableAtStart;
@ -54,8 +69,8 @@ namespace PoweredSoft.DynamicQuery
{ {
if (interceptor == null) throw new ArgumentNullException("interceptor"); if (interceptor == null) throw new ArgumentNullException("interceptor");
if (!Interceptors.Contains(interceptor)) if (!AddedInterceptors.Contains(interceptor))
Interceptors.Add(interceptor); AddedInterceptors.Add(interceptor);
} }
protected virtual IGroup InterceptGroup<TSource>(IGroup group) protected virtual IGroup InterceptGroup<TSource>(IGroup group)
@ -473,5 +488,16 @@ namespace PoweredSoft.DynamicQuery
await AfterReadInterceptors<TSource, TRecord>(pairs); await AfterReadInterceptors<TSource, TRecord>(pairs);
} }
public IReadOnlyList<IQueryInterceptor> ResolveInterceptors<TSource, TResult>(IQueryCriteria criteria, IQueryable<TSource> queryable)
{
var providedInterceptors = queryableInterceptorProviders.SelectMany(t => t.GetInterceptors<TSource, TResult>(criteria, queryable)).ToList();
var final = providedInterceptors
.Concat(AddedInterceptors)
.Distinct(new QueryInterceptorEqualityComparer())
.ToList();
return final;
}
} }
} }

View File

@ -0,0 +1,18 @@
using PoweredSoft.DynamicQuery.Core;
using System.Collections.Generic;
namespace PoweredSoft.DynamicQuery
{
public class QueryInterceptorEqualityComparer : IEqualityComparer<IQueryInterceptor>
{
public bool Equals(IQueryInterceptor x, IQueryInterceptor y)
{
return x.GetType() == y.GetType();
}
public int GetHashCode(IQueryInterceptor obj)
{
return obj.GetType().GetHashCode();
}
}
}