Operators
open FSharp.Interop.Dynamic auto-opens FSharp.Interop.Dynamic.TopLevelOperators.
? — get or invoke a named member
let length: int = "hello"?Length
let hello: string = "HelloWorld"?Substring(0, 5)
What happens depends on the result type F# infers:
- If
'TResultis not a function,?does a DLR get (InvokeGet)."hello"?Lengthis a property get. - If
'TResultis a function,?returns a callable."HelloWorld"?Substringhas typeint * int -> string(or whatever you bind), and applying it doesInvokeMember.
That is why target?Foo(1, 2) works as a method call: the application forces a function type.
A void CLR method is an unit-returning function:
let items = ResizeArray<string>()
items?Add("1")
?<- — set a named member
open System.Dynamic
let o = ExpandoObject()
o?Name <- "Ada"
Always a DLR set (InvokeSet). The result is unit.
!? — invoke the target itself
let add = (+)
let add3: int -> int = !?add 3
add3 4 // 7
!? is Dyn.invocation target Direct. Use it on:
- An F# function boxed as
obj - A Dynamitey curry:
!?Dynamic.Curry(...)?Format("Test {0}") - Anything the DLR can
Invoke
On a non-callable, both binders fail and you get AggregateException wrapping two RuntimeBinderExceptions.
Named arguments
Dynamitey InvokeArg via Dyn.namedArg:
open Dynamitey
let o = Build<ExpandoObject>.NewObject(Dyn.namedArg "One" 1)
pythonnet:
np?array([| 6.; 5.; 4. |], Dyn.namedArg "dtype" np?int32)
Static members
open System.Linq
let empty: int seq = Dyn.staticTarget<Enumerable> |> Dyn.invokeGeneric "Empty" [typeof<int>] ()
Dyn.staticContext typeof<Foo> is the same thing when you have a Type in hand instead of a type parameter.
Events
poco |> Dyn.memberAddAssign "Event" handler
poco |> Dyn.memberSubtractAssign "Event" handler
That is DLR += / -= on the named member, not F# event syntax.