Как выполнить код F #, найденный в строке в скомпилированной программе F #? - PullRequest
15 голосов
/ 21 июля 2009

Как выполнить код F # из строки в скомпилированной программе F #?

Ответы [ 3 ]

19 голосов
/ 22 июля 2009

Вот небольшой скрипт, который использует FSharp CodeDom для компиляции строки в сборку и динамической загрузки ее в сеанс скрипта.

Он использует расширение типа просто для того, чтобы разрешить полезные значения по умолчанию для аргументов (надеюсь, связанные функции будут поддерживать необязательные, именованные и параметры params в ближайшем будущем.)

#r "FSharp.Compiler.dll"
#r "FSharp.Compiler.CodeDom.dll"

open System
open System.IO
open System.CodeDom.Compiler
open Microsoft.FSharp.Compiler.CodeDom

let CompileFSharpString(str, assemblies, output) =
        use pro = new FSharpCodeProvider()
        let opt = CompilerParameters(assemblies, output)
        let res = pro.CompileAssemblyFromSource( opt, [|str|] )
        if res.Errors.Count = 0 then 
             Some(FileInfo(res.PathToAssembly)) 
        else None

let (++) v1 v2   = Path.Combine(v1, v2)    
let defaultAsms  = [|"System.dll"; "FSharp.Core.dll"; "FSharp.Powerpack.dll"|] 
let randomFile() = __SOURCE_DIRECTORY__ ++ Path.GetRandomFileName() + ".dll"   

type System.CodeDom.Compiler.CodeCompiler with 
    static member CompileFSharpString (str, ?assemblies, ?output) =
        let assemblies  = defaultArg assemblies defaultAsms
        let output      = defaultArg output (randomFile())
        CompileFSharpString(str, assemblies, output)     

// Our set of library functions.
let library = "

module Temp.Main
let f(x,y) = sin x + cos y
"
// Create the assembly
let fileinfo = CodeCompiler.CompileFSharpString(library)

// Import metadata into the FSharp typechecker
#r "0lb3lphm.del.dll"

let a = Temp.Main.f(0.5 * Math.PI, 0.0)     // val a : float = 2.0

// Purely reflective invocation of the function.
let asm = Reflection.Assembly.LoadFrom(fileinfo.Value.FullName)
let mth  = asm.GetType("Temp.Main").GetMethod("f")

// Wrap weakly typed function with strong typing.
let f(x,y) = mth.Invoke(null, [|box (x:float); box (y:float)|]) :?> float

let b = f (0.5 * Math.PI, 0.0)              // val b : float = 2.0

Чтобы использовать это в скомпилированной программе, вам понадобится чисто рефлексивный вызов.

Конечно, это игрушка по сравнению с полноценным API сценариев, который срочно потребовали многие из нас в сообществе.

удачи,

Danny

5 голосов
/ 21 июля 2009

Вы ищете функцию Eval?

Возможно, вы захотите посмотреть этот пост в блоге:

http://fsharpnews.blogspot.com/2007/02/symbolic-manipulation.html

Если вы читаете в своих выражениях такие символические структуры данных, их довольно легко оценить.


Или, возможно, вы ищете поддержку сценариев:

http://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx


Если вы действительно хотите динамическую компиляцию, вы можете сделать это с провайдером F # CodeDom.

3 голосов
/ 26 сентября 2016

На этом фронте было движение. Теперь вы можете компилировать с помощью FSharp.Compiler.Service

простой пример с использованием FSharp.Compiler.Service 5.0.0 от NuGet

open Microsoft.FSharp.Compiler.SimpleSourceCodeServices
let compile (codeText:string) = 
    let scs = SimpleSourceCodeServices()
    let src,dllPath = 
        let fn = Path.GetTempFileName()
        let fn2 = Path.ChangeExtension(fn, ".fs")
        let fn3 = Path.ChangeExtension(fn, ".dll")
        fn2,fn3
    File.WriteAllText(src,codeText)
    let errors, exitCode = scs.Compile [| "fsc.exe"; "-o"; dllPath; "-a";src; "-r"; "WindowsBase"; "-r" ;"PresentationCore"; "-r"; "PresentationFramework" |]
    match errors,exitCode with
    | [| |],0 -> Some dllPath
    | _ -> 
        (errors,exitCode).Dump("Compilation failed")
        File.Delete src
        File.Delete dllPath
        None

тогда это вопрос Assembly.LoadFrom(dllPath), чтобы получить его в текущем домене приложения.

с последующим отражением на основе вызовов в dll (или, возможно, Activator.CreateInstance)

Пример использования LinqPad

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...