3

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

andrewJames
  • 19,570
  • 8
  • 19
  • 51

1 Answers1

1

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
            |]),
        [||])

Josef Bláha
  • 1,033
  • 10
  • 21