Comment exécuter un code F # à partir d'une chaîne dans un programme F # compilé?Comment exécuter le code F # trouvé dans une chaîne dans un programme F # compilé?
Répondre
Voici un petit script qui utilise FSharp CodeDom pour compiler une chaîne dans un assembly et la charger dynamiquement dans la session de script.
Il utilise une extension de type simplement pour permettre les valeurs par défaut utiles sur les arguments (LET, espérons-fonctions liées soutiendront en option, les arguments nommés et params dans un avenir proche.)
#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
Pour utiliser dans un programme compilé vous auriez besoin de l'invocation purement réflective.
Bien sûr, il s'agit d'un jouet par rapport à une API de script complète que beaucoup d'entre nous dans la communauté ont demandé d'urgence.
bonne chance,
Danny
Êtes-vous à la recherche d'une fonction Eval?
Vous voudrez peut-être essayer de regarder ce blog:
http://fsharpnews.blogspot.com/2007/02/symbolic-manipulation.html
Si vous lisez dans vos expressions dans ce genre de datastructures symboliques, ils sont assez faciles à évaluer.
Ou, peut-être vous êtes à la recherche d'un soutien de script:
http://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx
Si vous voulez vraiment la compilation dynamique, vous pourriez le faire avec le fournisseur F # CodeDom.
Il a été sur ce front. Vous pouvez maintenant compiler en utilisant la FSharp.Compiler.Service
simple échantillon à l'aide FSharp.Compiler.Service 5.0.0 de 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
il est une question de Assembly.LoadFrom(dllPath)
pour l'obtenir dans le domaine de l'application actuelle.
suivie par une réflexion basée sur les appels dans le dll (ou peut-être Activator.CreateInstance
)
- 1. Tokenize une chaîne dans f #
- 2. F # Code dans un sous-dossier App_Code
- 3. F # lambdas dans les dossiers
- 4. Appeler le code F # de C#
- 5. F # - Afficher les résultats complets dans F # fenêtre interactive
- 6. F # enlever le code impératif - aide rapide
- 7. F # Ununit - reunit dans une fonction
- 8. Fonctions de passe dans F #
- 9. F # Constructeur
- 10. Permutations F #
- 11. Types d'union imbriqués dans F #
- 12. convertir amp; à & et? F Degré F Vb.net
- 13. Comment implémenter une classe abstraite en F #?
- 14. F # tuyau fourche
- 15. F # Ajouter un élément à une séquence
- 16. Comment récupérer un nom de fonction dans F #?
- 17. Comment actualiser un DataGrid à intervalles réguliers dans F #?
- 18. listes dans les structures dans F #?
- 19. Configuration de F # dans Visual Studio 2005
- 20. F #: Conversion d'une chaîne en un tableau d'octets
- 21. F # Fermeture
- 22. F/OSS pour le PIC24?
- 23. F # Méthodes statiques Dans la classe
- 24. F # Méthodes statiques privées
- 25. Comment créer une méthode d'extension (F #)?
- 26. Accès à un membre spécifique dans un F # tuple
- 27. F # convertir Array2 en une liste
- 28. F # Méthodes statiques multilignes
- 29. récursion explicite de type F dans #
- 30. F # int64 à int
C'est génial, exactement ce que j'ai besoin! – Cynede