Usted puede evaluar un F # Código Citas con coincidencia de patrones:
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 @>
Ver las F# PowerPack, Unquote, Foq proyectos de software libre o esta snippet para las implementaciones más completas.
Compilar un Código F # Cotización puedas define a dynamic method usando Reflection.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()
Compilar a un conjunto nuevo Reflection.Emit utilizar para generar un tipo con un método:
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 @>
Véase el Fil proyecto (F # a IL) para una implementación más completa.
No estoy seguro de si PowerPack es compatible con esto. Pero aparte, no recomendaría usar PowerPack en absoluto. Su código es a menudo con errores o muy lento. Escribir su propio compilador o evaluador desde cero utilizando System.Reflection.Emit probablemente dará mejores resultados. También existe el problema de que F # no optimiza las citas, por ejemplo, la coincidencia se convierte en una serie de if/then/else, en lugar de la instrucción de salto en CIL en la compilación normal de F #. – t0yv0
Hola, gracias por esto, creo que buscaré alternativas (como Reflection.Emit como mencionaste). – Ncc
Puede encontrar esto útil: http://stackoverflow.com/questions/2682475/converting-f-quotations-into-linq-expressions y http://stackoverflow.com/questions/1618682/linking-a-net-expression -tree-into-a-new-assembly – JPW