I'd like to get MethodInfo for caller-provided functions.
module MethodInfo =
let from0 (f: unit -> 'a) = (Func<'a>(f)).Method
let from1 (f: 'a -> 'b) = (Func<'a,'b>(f)).Method
let mi = MethodInfo.from0 (fun () -> 5)
mi.Invoke(null, Array.empty<obj>)
This compiles, but always throws "System.Reflection.TargetException : Non-static method requires a target."
The exception is not thrown if I pass an anonymous function directly to a method.
type MethodInfo =
static member from0 (f:Func<'a>) = f.Method
static member from1 (f:Func<'a,'b>) = f.Method
MethodInfo.from0 (fun () -> 5)
mi.Invoke(null, Array.empty<obj>)
Why does the conversion from F# functions to Func cause this exception? Is there a better way to get MethodInfo (some update since this old thread)?
CodePudding user response:
The issue is that the method returned by the delegate is not a static method, but an instance method that has to be invoked on an object that represents the closure (the object would normally capture e.g. variables that are used inside the function but are defined in the outer scope).
You can get your code to work if you return both the MethodInfo
and the target object of the delegate. Then you can pass the target object to Invoke
and you get back the expected result:
open System
module MethodInfo =
let from0 (f: unit -> 'a) =
let del = Func<'a>(f)
del.Target, del.Method
let target, mi = MethodInfo.from0 (fun () -> 5)
mi.Invoke(target, Array.empty<obj>)