Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a LINQ expression in F# for C# object initializer

I am using a .NET framework which allows to pass an object initializer LINQ expression when called from C#:

db.UpdateAdd( () => new InvoiceAccount { Quantity = 3 } );

The framework uses the expression from the argument to detect which fields should be updated.

Is there a possibility to construct same LINQ expression from F#? I am trying to use quotations to simulate the object initializer, but so far without any success. I've tried for example following:

let expr = 
        <@ fun () -> InvoiceAccount(Quantity = 3M) @>
        |> LeafExpressionConverter.QuotationToExpression 
        |> unbox<Expression<Func<InvoiceAccount>>>

db.UpdateAdd<InvoiceAccount>( expr )

which compiles without errors, but I get the following runtime error:

System.NotSupportedException: Could not convert the following F# Quotation to a LINQ Expression Tree

Sequential (Sequential (Value (), PropertySet (Some (returnVal), Quantity, [Call (None, MakeDecimal, [Value (3), Value (0), Value (0), Value (false), Value (0uy)])])), returnVal)

at Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.failConvert(FSharpExpr inp) in D:\a_work\1\s\src\fsharp\FSharp.Core\Linq.fs:line 666

like image 310
Marek Vaculciak Avatar asked Oct 16 '25 23:10

Marek Vaculciak


1 Answers

This constructs an equivalent expression:

let invoiceAccountCtor = typedefof<InvoiceAccount>.GetConstructor([||])
let quantityProp = typedefof<InvoiceAccount>.GetMember(nameof Unchecked.defaultof<InvoiceAccount>.Quantity).Single()
let expr =
    Expression.Lambda(
        Expression.MemberInit(
            Expression.New(invoiceAccountCtor),
            [|
                Expression.Bind(quantityProp, Expression.Constant(3)) :> MemberBinding
            |]),
        [||])

like image 52
Josef Bláha Avatar answered Oct 18 '25 21:10

Josef Bláha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!