使用反射创建Action <'T>的实例

Dan*_*iel 5 reflection f# delegates

我如何创建Action<'T>使用反射的实例?这就是我所拥有的:

let makeAction (typ:Type) (f:'T -> unit) = 
  let actionType = typedefof<Action<_>>.MakeGenericType(typ)
  let converter = FSharpFunc.ToConverter(f)
  Delegate.CreateDelegate(actionType, converter.Method)
Run Code Online (Sandbox Code Playgroud)

哪个barf:

System.ArgumentException:绑定到目标方法时出错.
在System.Delegate.CreateDelegate(Type type,MethodInfo方法,Boolean throwOnBindFailure)

'T是一个typ实现的接口.

Tom*_*cek 5

我认为有两个问题。第一个是您需要调用CreateDelegate带有三个参数的重载。附加参数指定应在其上调用该方法的实例。

第二个问题是Converter<'T, unit>实际编译为返回的方法,Microsoft.FSharp.Core.Unit而不是返回的方法void。我不确定是否有更简单的解决方法,但是您可以定义一个具有方法的包装器。成员被编译为类似于C#,因此void在这种情况下,单元类型将被编译:

open System

type Wrapper<'T>(f:'T -> unit) =
  member x.Invoke(a:'T) = f a

let makeAction (typ:Type) (f:'T -> unit) = 
  let actionType = typedefof<Action<_>>.MakeGenericType(typ)
  let wrapperType = typedefof<Wrapper<_>>.MakeGenericType(typ)
  let wrapped = Wrapper<_>(f)
  Delegate.CreateDelegate(actionType, wrapped, wrapped.GetType().GetMethod("Invoke"))

makeAction (typeof<int>) (printfn "%d")
Run Code Online (Sandbox Code Playgroud)

编辑 -做了一些小的改动以使其在您的场景中实际起作用(带有界面)