コード引用をアセンブリにコンパイルする方法があるかどうかを知りたいですか?F#コード引用をアセンブリにコンパイルする方法
私は例えば、Exp<_>
オブジェクト上CompileUntyped()
またはCompile()
を呼び出すことが可能であることを理解:
let x = <@ 1 * 2 @>
let com = x.Compile()
はしかし、どのように私は、アセンブリとしてディスクにcom
を持続することができますか?
ありがとうございました。
コード引用をアセンブリにコンパイルする方法があるかどうかを知りたいですか?F#コード引用をアセンブリにコンパイルする方法
私は例えば、Exp<_>
オブジェクト上CompileUntyped()
またはCompile()
を呼び出すことが可能であることを理解:
let x = <@ 1 * 2 @>
let com = x.Compile()
はしかし、どのように私は、アセンブリとしてディスクにcom
を持続することができますか?
ありがとうございました。
あなたはパターンマッチングとF#コード名言評価することができます。
open Microsoft.FSharp.Quotations.Patterns
let rec eval = function
| Value(v,t) -> v
| Call(None,mi,args) -> mi.Invoke(null, evalAll args)
| arg -> raise <| System.NotSupportedException(arg.ToString())
and evalAll args = [|for arg in args -> eval arg|]
let x = eval <@ 1 * 3 @>
はF# PowerPack、Unquote、Foq OSSプロジェクトや、より完全な実装については、このsnippetを参照してください。 F#コード見積をコンパイルするに
あなたがdefine a dynamic methodReflection.Emitを使用することができます
open System.Reflection.Emit
let rec generate (il:ILGenerator) = function
| Value(v,t) when t = typeof<int> ->
il.Emit(OpCodes.Ldc_I4, v :?> int)
| Call(None,mi,args) ->
generateAll il args
il.EmitCall(OpCodes.Call, mi, null)
| arg -> raise <| System.NotSupportedException(arg.ToString())
and generateAll il args = for arg in args do generate il arg
type Marker = interface end
let compile quotation =
let f = DynamicMethod("f", typeof<int>, [||], typeof<Marker>.Module)
let il = f.GetILGenerator()
quotation |> generate il
il.Emit(OpCodes.Ret)
fun() -> f.Invoke(null,[||]) :?> int
let f = compile <@ 1 + 3 @>
let x = f()
の方法とタイプを生成するReflection.Emitを使用して、再びアセンブリにコンパイルするには:
open System
open System.Reflection
let createAssembly quotation =
let name = "GeneratedAssembly"
let domain = AppDomain.CurrentDomain
let assembly = domain.DefineDynamicAssembly(AssemblyName(name), AssemblyBuilderAccess.RunAndSave)
let dm = assembly.DefineDynamicModule(name+".dll")
let t = dm.DefineType("Type", TypeAttributes.Public ||| TypeAttributes.Class)
let mb = t.DefineMethod("f", MethodAttributes.Public, typeof<int>, [||])
let il = mb.GetILGenerator()
quotation |> generate il
il.Emit(OpCodes.Ret)
assembly.Save("GeneratedAssembly.dll")
createAssembly <@ 1 + 1 @>
を参照してください。より完全な実装のためのFilプロジェクト(F#からIL)。
PowerPackがこれをサポートしているかどうかはわかりません。しかし、私はPowerPackの使用をお勧めしません。そのコードは頻繁にバグがあり、遅すぎます。 System.Reflection.Emitを使用して独自のコンパイラまたは評価版をゼロから作成すると、おそらくより良い結果が得られます。また、F#が引用を最適化しないという問題もあります。たとえば、通常のF#コンパイルのCILにあるジャンプ命令ではなく、一連のif/then/elseになります。 – t0yv0
こんにちは、ありがとう、私はそれら(Reflection.Emitあなたが述べたように)それらの代替案を検討すると思います。 – Ncc
これは便利です:http://stackoverflow.com/questions/2682475/converting-f-quotations-into-linq-expressions and http://stackoverflow.com/questions/1618682/linking-a-net-expression新しいアセンブリを作成する – JPW