Skip to content

Commit 48bb152

Browse files
xperiandriViktor Tochonov
authored andcommitted
WIP implementing application of ObjectListFilter to IQueryable
1 parent 2e4699f commit 48bb152

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/FSharp.Data.GraphQL.Server.Middleware/ObjectListFilter.fs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
namespace FSharp.Data.GraphQL.Server.Middleware
22

33
open System
4+
open System.Linq
5+
open System.Linq.Expressions
6+
open System.Runtime.InteropServices
7+
open Microsoft.FSharp.Quotations
48

59
/// A filter definition for a field value.
610
type FieldFilter<'Val> =
@@ -55,3 +59,117 @@ module ObjectListFilter =
5559

5660
/// Creates a new ObjectListFilter representing a NOT opreation for the existing one.
5761
let ( !!! ) filter = Not filter
62+
63+
//[<AutoOpen>]
64+
//module ObjectListFilterExtensions =
65+
66+
// type ObjectListFilter with
67+
68+
// member filter.Apply<'T, 'D>(query : IQueryable<'T>,
69+
// compareDiscriminator : Expr<'T -> 'D -> 'D> | null,
70+
// getDiscriminatorValue : (Type -> 'D) | null) =
71+
// filter.Apply(query, compareDiscriminator, getDiscriminatorValue)
72+
73+
// member filter.Apply<'T, 'D>(query : IQueryable<'T>,
74+
// [<Optional>] getDiscriminator : Expr<'T -> 'D> | null,
75+
// [<Optional>] getDiscriminatorValue : (Type -> 'D) | null) =
76+
// // Helper to create parameter expression for the lambda
77+
// let param = Expression.Parameter(typeof<'T>, "x")
78+
79+
// // Helper to get property value
80+
// let getPropertyExpr fieldName =
81+
// Expression.PropertyOrField(param, fieldName)
82+
83+
// // Helper to create lambda from body expression
84+
// let makeLambda (body: Expression) =
85+
// let delegateType = typedefof<Func<_,_>>.MakeGenericType([|typeof<'T>; body.Type|])
86+
// Expression.Lambda(delegateType, body, param)
87+
88+
// // Helper to create Where expression
89+
// let whereExpr predicate =
90+
// let whereMethod =
91+
// typeof<Queryable>.GetMethods()
92+
// |> Seq.where (fun m -> m.Name = "Where")
93+
// |> Seq.find (fun m ->
94+
// let parameters = m.GetParameters()
95+
// parameters.Length = 2
96+
// && parameters[1].ParameterType.GetGenericTypeDefinition() = typedefof<Expression<Func<_,_>>>)
97+
// |> fun m -> m.MakeGenericMethod([|typeof<'T>|])
98+
// Expression.Call(whereMethod, [|query.Expression; makeLambda predicate|])
99+
100+
// // Helper for discriminator comparison
101+
// let buildTypeDiscriminatorCheck (t: Type) =
102+
// match getDiscriminator, getDiscriminatorValue with
103+
// | null, _ | _, null -> None
104+
// | discExpr, discValueFn ->
105+
// let compiled = QuotationEvaluator.Eval(discExpr)
106+
// let discriminatorValue = discValueFn t
107+
// let discExpr = getPropertyExpr "__discriminator" // Assuming discriminator field name
108+
// let valueExpr = Expression.Constant(discriminatorValue)
109+
// Some(Expression.Equal(discExpr, valueExpr))
110+
111+
// // Main filter logic
112+
// let rec buildFilterExpr filter =
113+
// match filter with
114+
// | NoFilter -> query.Expression
115+
// | And (f1, f2) ->
116+
// let q1 = buildFilterExpr f1 |> Expression.Lambda<Func<IQueryable<'T>>>|> _.Compile().Invoke()
117+
// buildFilterExpr f2 |> Expression.Lambda<Func<IQueryable<'T>>> |> _.Compile().Invoke(q1).Expression
118+
// | Or (f1, f2) ->
119+
// let expr1 = buildFilterExpr f1
120+
// let expr2 = buildFilterExpr f2
121+
// let unionMethod =
122+
// typeof<Queryable>.GetMethods()
123+
// |> Array.find (fun m -> m.Name = "Union")
124+
// |> fun m -> m.MakeGenericMethod([|typeof<'T>|])
125+
// Expression.Call(unionMethod, [|expr1; expr2|])
126+
// | Not f ->
127+
// let exceptMethod =
128+
// typeof<Queryable>.GetMethods()
129+
// |> Array.find (fun m -> m.Name = "Except")
130+
// |> fun m -> m.MakeGenericMethod([|typeof<'T>|])
131+
// Expression.Call(exceptMethod, [|query.Expression; buildFilterExpr f|])
132+
// | Equals f ->
133+
// Expression.Equal(getPropertyExpr f.FieldName, Expression.Constant(f.Value)) |> whereExpr
134+
// | GreaterThan f ->
135+
// Expression.GreaterThan(getPropertyExpr f.FieldName, Expression.Constant(f.Value)) |> whereExpr
136+
// | LessThan f ->
137+
// Expression.LessThan(getPropertyExpr f.FieldName, Expression.Constant(f.Value)) |> whereExpr
138+
// | StartsWith f ->
139+
// let methodInfo = typeof<string>.GetMethod("StartsWith", [|typeof<string>|])
140+
// Expression.Call(getPropertyExpr f.FieldName, methodInfo, Expression.Constant(f.Value)) |> whereExpr
141+
// | EndsWith f ->
142+
// let methodInfo = typeof<string>.GetMethod("EndsWith", [|typeof<string>|])
143+
// Expression.Call(getPropertyExpr f.FieldName, methodInfo, Expression.Constant(f.Value)) |> whereExpr
144+
// | Contains f ->
145+
// let methodInfo = typeof<string>.GetMethod("Contains", [|typeof<string>|])
146+
// Expression.Call(getPropertyExpr f.FieldName, methodInfo, Expression.Constant(f.Value)) |> whereExpr
147+
// | OfTypes types ->
148+
// match types.Value with
149+
// | [] -> query.Expression // No types specified, return original query
150+
// | types ->
151+
// let typeChecks =
152+
// types
153+
// |> List.choose buildTypeDiscriminatorCheck
154+
// |> List.fold (fun acc expr ->
155+
// match acc with
156+
// | None -> Some expr
157+
// | Some prevExpr -> Some(Expression.OrElse(prevExpr, expr))) None
158+
159+
// match typeChecks with
160+
// | None -> query.Expression
161+
// | Some expr -> whereExpr expr
162+
// | FilterField f ->
163+
// let propExpr = getPropertyExpr f.FieldName
164+
// match propExpr.Type.GetInterfaces()
165+
// |> Array.tryFind (fun t ->
166+
// t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<IQueryable<_>>) with
167+
// | Some queryableType ->
168+
// let elementType = queryableType.GetGenericArguments().[0]
169+
// let subFilter = f.Value
170+
// let subQuery = Expression.Convert(propExpr, queryableType)
171+
// Expression.Call(typeof<Queryable>, "Any", [|elementType|], subQuery) |> whereExpr
172+
// | None -> query.Expression
173+
174+
// // Create and execute the final expression
175+
// query.Provider.CreateQuery<'T>(buildFilterExpr filter)

0 commit comments

Comments
 (0)