1- using AutoMapper ;
2- using AutoMapper . Internal ;
3- using AutoMapper . QueryableExtensions ;
4- using Microsoft . EntityFrameworkCore ;
5- using Microsoft . EntityFrameworkCore . Infrastructure ;
6- using Swashbuckle . AspNetCore . SwaggerGen ;
1+ using System . Collections . Generic ;
72using System . Globalization ;
83using System . Linq . Expressions ;
94using System . Reflection ;
105using System . Reflection . Emit ;
116using System . Text . Json ;
127using System . Text . Json . Nodes ;
138using System . Text . Json . Serialization ;
9+ using AutoMapper ;
10+ using AutoMapper . Internal ;
11+ using AutoMapper . QueryableExtensions ;
12+ using Microsoft . EntityFrameworkCore ;
13+ using Microsoft . EntityFrameworkCore . Infrastructure ;
14+ using Swashbuckle . AspNetCore . SwaggerGen ;
1415
1516namespace Infragistics . QueryBuilder . Executor
1617{
@@ -33,6 +34,15 @@ public static object[] Run<TSource, TTarget>(this IQueryable<TSource> source, Qu
3334 return db is not null ? BuildQuery < TSource , TTarget > ( db , source , query , mapper ) . ToArray ( ) : Array . Empty < object > ( ) ;
3435 }
3536
37+ public static MethodInfo ? GetGenericMethod ( Type executorType , int attributeCount , Type [ ] genericArgs )
38+ {
39+ var method = executorType
40+ . GetMethods ( BindingFlags . Static | BindingFlags . Public )
41+ . FirstOrDefault ( m => m . CustomAttributes . Count ( ) == attributeCount ) ;
42+
43+ return method ? . MakeGenericMethod ( genericArgs ) ;
44+ }
45+
3646 private static IQueryable < object > BuildQuery < TSource , TTarget > ( DbContext db , IQueryable < TSource > source , Query ? query , IMapper ? mapper = null )
3747 {
3848 if ( query is null )
@@ -224,7 +234,21 @@ private static IEnumerable<dynamic> RunSubquery(DbContext db, Query? query)
224234 {
225235 var t = query ? . Entity . ToLower ( CultureInfo . InvariantCulture ) ?? string . Empty ;
226236 var p = db . GetType ( ) . GetProperty ( t , BindingFlags . IgnoreCase | BindingFlags . Public | BindingFlags . Instance ) ?? throw new InvalidOperationException ( $ "Property '{ t } ' not found on type '{ db . GetType ( ) } '") ;
227- return p . GetValue ( db ) is not IQueryable < dynamic > q ? Array . Empty < dynamic > ( ) : [ .. q . Run ( query ) ] ;
237+
238+ var methods = typeof ( QueryExecutor ) . GetMethods ( BindingFlags . Static | BindingFlags . Public ) ;
239+ var method = methods ? . FirstOrDefault ( m => m . CustomAttributes . Count ( ) == 1 ) ;
240+ var dbSet = p . GetValue ( db ) ;
241+ var genericType = p . PropertyType . GetGenericArguments ( ) . FirstOrDefault ( ) ;
242+
243+ if ( dbSet != null && genericType != null )
244+ {
245+
246+ var genericMethod = GetGenericMethod ( typeof ( QueryExecutor ) , 1 , [ genericType ] ) ;
247+
248+ var queryable = dbSet ? . GetType ( ) . GetMethod ( "AsQueryable" ) ? . Invoke ( dbSet , null ) ;
249+ return genericMethod ? . Invoke ( null , [ queryable , query ] ) as IEnumerable < dynamic > ?? Array . Empty < dynamic > ( ) ;
250+ }
251+ return Enumerable . Empty < dynamic > ( ) ;
228252 }
229253
230254 private static dynamic ? ProjectField ( object ? obj , string field )
@@ -242,13 +266,18 @@ private static Expression GetSearchValue(JsonValue? jsonVal, Type targetType)
242266 }
243267
244268 var nonNullableType = Nullable . GetUnderlyingType ( targetType ) ?? targetType ;
245- var value = jsonVal . Deserialize ( targetType ) ;
246269
247- if ( nonNullableType . IsEnum && value is string )
270+ if ( nonNullableType . IsEnum )
248271 {
249- return Expression . Constant ( Enum . Parse ( nonNullableType , ( string ) value ) ) ;
272+ var enumValue = jsonVal . Deserialize < string > ( ) ;
273+ if ( enumValue != null )
274+ {
275+ return Expression . Constant ( Enum . Parse ( nonNullableType , enumValue ) ) ;
276+ }
250277 }
251278
279+ var value = jsonVal . Deserialize ( targetType ) ;
280+
252281 var convertedValue = Convert . ChangeType ( value , nonNullableType , CultureInfo . InvariantCulture ) ;
253282 return Expression . Constant ( convertedValue , targetType ) ;
254283 }
0 commit comments