如何从已编译的F#程序中的字符串执行F#代码?
这是一个使用FSharp CodeDom将字符串编译成程序集并将其动态加载到脚本会话中的小脚本.
它使用类型扩展只是为了允许参数有用的默认值(希望绑定函数在不久的将来支持可选,命名和参数参数.)
#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相比,这是一个玩具.
祝你好运,
丹尼
您在寻找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提供程序.