2011-07-26 11 views
5

リフレクションを使用してAction<'T>のインスタンスを作成するにはどうすればよいですか?ここで私が持っているものです。リフレクションを使用してアクション<'T>のインスタンスを作成する

System.ArgumentExceptionの:エラーがメソッドをターゲットに結合してbarfs

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

を。 System.Delegate.CreateDelegate(タイプタイプ、METHODINFO法、ブールthrowOnBindFailure)で

'T

、そのtyp実装のインタフェースです。

+0

リフレクションを使用してこれを行う特別な理由はありますか? @Ankur:はい、私は '' a'(あなたの例では)を知りませんので、これは簡単です: 'let makeAction(f: 'a - > unit)= new Action <'a>(f)' – Ankur

+0

@Ankur:コンパイル時に – Daniel

+0

私が正しくあなたを得ているかどうかはわかりませんが、ここでの '' a''はあなたのコードで '' T'と同じです。すなわち、渡された 'f'値に応じて解決されるジェネリック型です。渡された 'f'関数をラップするアクション型が必要ですか? – Ankur

答えて

3

私には2つの問題があると思います。最初の1つは、CreateDelegateオーバーロードに3つの引数を必要とする呼び出しをする必要があることです。 additional引数は、メソッドを呼び出すインスタンスを指定します。

第2の問題は、voidを返すメソッドではなく、Microsoft.FSharp.Core.Unitを返すメソッドとして実際にコンパイルすることです。簡単な回避策があるかどうかはわかりませんが、メソッドを持つラッパーを定義できます。ユニットの種類が、その場合にはvoidとしてコンパイルされますので、メンバーは、C#のように見えるようにコンパイルされています

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

EDIT -

それは実際に(インターフェイスで)あなたのシナリオで動作させるためにマイナーチェンジをしました
+0

素晴らしいです。ありがとう!私は 'MethodInfo'を取得するために' Converter'を作成していました。私はF#関数からそれをどうやって取得するのか分かりませんでした。 – Daniel

+0

@Daniel - 関数 'f'を持っている場合、' f.GetType()。GetMethod( "Invoke") 'を使うこともできますが、これは' unit'を返すメソッドを提供します。この場合。 –

+0

ええ、私はそれを最初に試み、同じ発見をしました。 – Daniel

関連する問題