Bạn có thể đánh giá một chiếc F Báo giá # Mã với mô hình kết hợp:
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 @>
Xem F# PowerPack, Unquote, Foq dự án OSS hoặc snippet này cho việc triển khai hoàn chỉnh hơn.
Để biên dịch một F # Mã báo giá bạn có thể sử dụng 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()
Để biên dịch cho một assembly một lần nữa sử dụng Reflection.Emit để tạo ra một kiểu với một phương pháp:
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 @>
Xem Fil dự án (F # đến IL) để thực hiện đầy đủ hơn.
Tôi không chắc liệu PowerPack có hỗ trợ điều này hay không. Nhưng như một sang một bên, tôi sẽ không khuyên bạn nên sử dụng PowerPack. Mã của họ thường bị lỗi hoặc quá chậm. Viết trình biên dịch hoặc bộ đánh giá của riêng bạn từ đầu bằng System.Reflection.Emit có thể sẽ cho kết quả tốt hơn. Ngoài ra còn có vấn đề là F # không tối ưu hóa các trích dẫn, ví dụ kết hợp sẽ trở thành một chuỗi nếu/sau đó/khác, thay vì lệnh nhảy, nó nằm trong CIL trong quá trình biên dịch F # bình thường. – t0yv0
Xin chào, cảm ơn vì điều này, tôi đoán tôi sẽ xem xét các lựa chọn thay thế cho họ (chẳng hạn như Reflection.Emit như bạn đã đề cập). – Ncc
Bạn có thể thấy điều này hữu ích: http://stackoverflow.com/questions/2682475/converting-f-quotations-into-linq-expressions và http://stackoverflow.com/questions/1618682/linking-a-net-expression -tree-in-a-new-assembly – JPW