Consider the following code with downcasting:
let list = [1; 2; 4] :> obj
// Successful
let list2 = list :?> int list
// Exception - System.InvalidCastException
let list3 = list :?> obj list
let list4 = list :?> _ list
Basically I want to downcast to a list collection but really ignore the generic type argument. However, it throws InvalidCastException exception for list3 and list4. Is there a way to achieve this?
As a context, I am trying to accept list of Linq expression for eager fetching from DBContext like this to address N+1 select problem for dependent entities within GraphQL queries. I cannot really downcast to a specific type. The expression must be downcasted to a generic version Expression<Func<Tenant,_>> within the loop:
let getTenants (db: Context) takeItems skipItems =
let expr1 =
<@ Func<_, _>(fun x -> x.TenantConfig) @>
|> LeafExpressionConverter.QuotationToExpression
let expr2 =
<@ Func<_, _>(fun x -> x.Invitations) @>
|> LeafExpressionConverter.QuotationToExpression
// This list of includes expressions will be passed by the caller eventually
let exprs = [expr1; expr2]
let q =
List.fold
(fun (acc: IQueryable<Tenant>) (x: Expression) ->
let expr = x :?> Expression<Func<Tenant, _>>
acc.Include(expr) :> IQueryable<Tenant>)
(db.Tenant.AsQueryable())
exprs
query {
for tenant in q do
skip skipItems
take takeItems
select tenant
}
|> fun x -> x.ToListAsync()
|> Async.AwaitTask
|> Async.map Seq.toList
I can use the string based version of IQueryable<'a>.Include but that tosses the type-safety completely out of window