Я думаю, что есть две проблемы. Во-первых, вам нужно вызвать перегрузку 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")
РЕДАКТИРОВАТЬ - Внесены незначительные изменения, чтобы он действительно работал в вашем сценарии (с интерфейсом)