1

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)?

farlee2121
  • 2,959
  • 4
  • 29
  • 41
  • 1
    This problem is tracked here https://github.com/fsharp/fslang-suggestions/issues/1083 – JL0PD Jun 27 '22 at 16:06
  • 1
    What version of F# are you using? I tried running this in VS in F# Interactive ("F# Interactive version 12.0.1.0 for F# 6.0") and it does not throw an exception for me. – Tomas Petricek Jun 28 '22 at 00:23
  • I realized that I never show invoking the MethodInfo. I've added it to the sample. With that update it fails with FSharp.Core 6.0.4 – farlee2121 Jun 28 '22 at 01:14

1 Answers1

4

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>)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • Interesting. The lambda is considered static one way, and not the other, so I fooled myself into thinking I didn't need the target. – farlee2121 Jun 28 '22 at 23:31