Jack Fox
Jack Fox

Reputation: 945

Is it possible to pass a F# function by Reflection?

Is it possible to pass a F# function by Reflection?

(*in module A*)
type Foo() =
    static member bar n = {1..n}

let functionUsingFoobar (x:(int -> #('a seq)) n =
    let z = BarFoo.ofSeq (x n)
    z.count

(* in module B
here is where I want to pass Foo.bar by reflection*)
let y = functionUsingFoobar Foo.bar 1000

I cannot invoke the member without the args parameter, so partial function application through InvokeMember cannot work.

let foo = new Foo()
let z = foo.GetType().InvokeMember("bar", System.Reflection.BindingFlags.InvokeMethod, null, foo, [|1000|])
(*tried null, [||], [|null|] for args parameter*)

I'm out of ideas how to pass the function by reflection

Upvotes: 1

Views: 361

Answers (2)

John Palmer
John Palmer

Reputation: 25526

If this is what I think you want, it works just fine

type Foo() =
    static member bar n = {1..n}

let functionUsingFoobar (x:(int -> #('a seq))) n =
    (x n) |> Seq.length

let y = functionUsingFoobar Foo.bar 1000
let foo = new Foo()
let z = fun t -> foo.GetType().InvokeMember("bar", System.Reflection.BindingFlags.InvokeMethod, null, foo, [|t|])

Upvotes: 0

kvb
kvb

Reputation: 55185

The problem is that GetMethod returns a MethodInfo, but you need an F# function value. The easiest way to overcome this mismatch is probably to use CreateDelegate to create a .NET delegate from the method, and then treat the Invoke method as a function value of the correct type:

let d = 
    typeof<Foo>.GetMethod("bar").CreateDelegate(typeof<System.Func<int,seq<int>>>) 
    :?> System.Func<int,seq<int>>
functionUsingFooBar d.Invoke 1000

Upvotes: 2

Related Questions