web-dev-qa-db-fra.com

Quel est le meilleur langage de script à intégrer dans une application de bureau C #?

Nous sommes en train d’écrire une application de bureau riche et complexe et devons offrir une flexibilité dans les formats de rapport afin que nous puissions exposer notre modèle objet à une langue de script. C'était à l'époque où cela signifiait VBA (ce qui est toujours une option), mais le dérivé du code géré VSTA (je pense) semble avoir flétri sur la vigne.

Quel est maintenant le meilleur choix pour un langage de script intégré sur Windows .NET?

94
Ewan Makepeace

J'ai utilisé CSScript avec des résultats étonnants. Cela réduisait vraiment le nombre de liaisons et autres tâches de bas niveau dans mes applications scriptables. 

21
Hector Sosa Jr

Personnellement, j'utiliserais C # comme langage de script. Le framework .NET (et Mono, merci Matthew Scharley) inclut en fait les compilateurs de chacun des langages .NET dans le framework lui-même.

Fondamentalement, la mise en œuvre de ce système comporte deux parties.

  1. Permettez à l’utilisateur de compiler le code C’est relativement facile et ne peut être fait qu’en quelques lignes de code (bien que vous souhaitiez peut-être ajouter une boîte de dialogue d’erreur, qui serait probablement composée d’une vingtaine de lignes supplémentaires sur la façon dont vous voulez qu'il soit utilisable).

  2. Créez et utilisez les classes contenues dans l’assembly compilé C’est un peu plus difficile que l’étape précédente (nécessite un peu de réflexion). Fondamentalement, vous devriez simplement traiter l’Assemblée compilée comme un "plug-in" du programme. Il existe de nombreux tutoriels sur les différentes manières de créer un système de plug-in en C # (Google est votre ami).

J'ai implémenté une application "rapide" pour montrer comment implémenter ce système (inclut 2 scripts de travail!). C’est le code complet de l’application, il suffit de créer un nouveau code et de le coller dans le fichier "program.cs" . À ce stade, je dois m'excuser pour le gros morceau de code que je vais coller (je je ne voulais pas que ce soit si grand, mais je me suis un peu emporté avec mes commentaires)


using System;
using System.Windows.Forms;
using System.Reflection;
using System.CodeDom.Compiler;

namespace ScriptingInterface
{
    public interface IScriptType1
    {
        string RunScript(int value);
    }
}

namespace ScriptingExample
{
    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {

            // Lets compile some code (I'm lazy, so I'll just hardcode it all, i'm sure you can work out how to read from a file/text box instead
            Assembly compiledScript = CompileCode(
                "namespace SimpleScripts" +
                "{" +
                "    public class MyScriptMul5 : ScriptingInterface.IScriptType1" +
                "    {" +
                "        public string RunScript(int value)" +
                "        {" +
                "            return this.ToString() + \" just ran! Result: \" + (value*5).ToString();" +
                "        }" +
                "    }" +
                "    public class MyScriptNegate : ScriptingInterface.IScriptType1" +
                "    {" +
                "        public string RunScript(int value)" +
                "        {" +
                "            return this.ToString() + \" just ran! Result: \" + (-value).ToString();" +
                "        }" +
                "    }" +
                "}");

            if (compiledScript != null)
            {
                RunScript(compiledScript);
            }
        }

        static Assembly CompileCode(string code)
        {
            // Create a code provider
            // This class implements the 'CodeDomProvider' class as its base. All of the current .Net languages (at least Microsoft ones)
            // come with thier own implemtation, thus you can allow the user to use the language of thier choice (though i recommend that
            // you don't allow the use of c++, which is too volatile for scripting use - memory leaks anyone?)
            Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider();

            // Setup our options
            CompilerParameters options = new CompilerParameters();
            options.GenerateExecutable = false; // we want a Dll (or "Class Library" as its called in .Net)
            options.GenerateInMemory = true; // Saves us from deleting the Dll when we are done with it, though you could set this to false and save start-up time by next time by not having to re-compile
            // And set any others you want, there a quite a few, take some time to look through them all and decide which fit your application best!

            // Add any references you want the users to be able to access, be warned that giving them access to some classes can allow
            // harmful code to be written and executed. I recommend that you write your own Class library that is the only reference it allows
            // thus they can only do the things you want them to.
            // (though things like "System.Xml.dll" can be useful, just need to provide a way users can read a file to pass in to it)
            // Just to avoid bloatin this example to much, we will just add THIS program to its references, that way we don't need another
            // project to store the interfaces that both this class and the other uses. Just remember, this will expose ALL public classes to
            // the "script"
            options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            // Compile our code
            CompilerResults result;
            result = csProvider.CompileAssemblyFromSource(options, code);

            if (result.Errors.HasErrors)
            {
                // TODO: report back to the user that the script has errored
                return null;
            }

            if (result.Errors.HasWarnings)
            {
                // TODO: tell the user about the warnings, might want to Prompt them if they want to continue
                // runnning the "script"
            }

            return result.CompiledAssembly;
        }

        static void RunScript(Assembly script)
        {
            // Now that we have a compiled script, lets run them
            foreach (Type type in script.GetExportedTypes())
            {
                foreach (Type iface in type.GetInterfaces())
                {
                    if (iface == typeof(ScriptingInterface.IScriptType1))
                    {
                        // yay, we found a script interface, lets create it and run it!

                        // Get the constructor for the current type
                        // you can also specify what creation parameter types you want to pass to it,
                        // so you could possibly pass in data it might need, or a class that it can use to query the Host application
                        ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
                        if (constructor != null && constructor.IsPublic)
                        {
                            // lets be friendly and only do things legitimitely by only using valid constructors

                            // we specified that we wanted a constructor that doesn't take parameters, so don't pass parameters
                            ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1;
                            if (scriptObject != null)
                            {
                                //Lets run our script and display its results
                                MessageBox.Show(scriptObject.RunScript(50));
                            }
                            else
                            {
                                // hmmm, for some reason it didn't create the object
                                // this shouldn't happen, as we have been doing checks all along, but we should
                                // inform the user something bad has happened, and possibly request them to send
                                // you the script so you can debug this problem
                            }
                        }
                        else
                        {
                            // and even more friendly and explain that there was no valid constructor
                            // found and thats why this script object wasn't run
                        }
                    }
                }
            }
        }
    }
}
107
Grant Peters

IronPython . Voici un aperçu de comment l’intégrer .

36
Ben Hoffstein

Le moteur PowerShell a été conçu pour être facilement intégré dans une application afin de le rendre scriptable. En fait, la CLI PowerShell n’est qu’une interface texte avec le moteur.

Edit: Voir http://blogs.msdn.com/powershell/archive/2007/08/29/making-applications-scriptable-via-powershell.aspx

19
Rodrick Chapman

Boo langue.

13
jop

Mon langage de script de choix serait Lua ces jours-ci. Il est petit, rapide, propre, entièrement documenté, bien pris en charge, possède une grande communauté , il est utilisé par de nombreuses grandes entreprises du secteur [ (Adobe, Blizzard, EA Games), qui vaut vraiment la peine d’être essayé.

Pour l'utiliser avec les langages .NET, le projet LuaInterface vous fournira tout ce dont vous avez besoin. 

8
Remo.D

Pourquoi ne pas essayer le C #? Mono a un nouveau nouveau projet spécialement conçu pour évaluer dynamiquement le C #:

http://tirania.org/blog/archive/2008/Sep-10.html

3
DAC

IronRuby comme mentionné ci-dessus. Un projet intéressant pour moi en tant que programmeur C # est le support de C # Eval dans Mono . Mais ce n'est pas encore disponible (fera partie de Mono 2.2).

2
Borek Bernard

Un autre vote pour IronPython. L’intégration est simple, l’interopérabilité avec les classes .Net est simple, et bien, c’est Python.

2
Robert Rossney

Essayez Ela . C'est un langage fonctionnel similaire à Haskell et qui peut être intégré dans toute application .Net. Même il a IDE simple mais utilisable.

Je peux suggérer S # que je maintiens actuellement. C'est un projet open source, écrit en C # et conçu pour les applications .NET.

Initialement (2007-2009), il était hébergé sur http://www.codeplex.com/scriptdotnet , mais il a récemment été déplacé vers github.

1
Peter

JScript.NET est un bon exemple. Fiddler l'utilise.

1
Mark Cidade

Je viens de créer un plug-in pour un client, lui permettant d'écrire du code C # dans des modules agissant comme le fait VBA pour Office. 

0
Mark

J'ai déjà utilisé Lua avant; dans une application Delphi, mais il peut être intégré à beaucoup de choses. Il est utilisé dans Photoshop Lightroom d'Adobe .

0
Tony

J'aime les scripts avec C # lui-même. Maintenant, en 2013, le script C # est assez bien supporté, de plus en plus de librairies sont disponibles.

Mono supporte parfaitement le script code C # , et vous pouvez l'utiliser avec .NET en incluant simplement le Mono.CSharp.dll dans votre application. Pour l'application de script C # que j'ai créée, consultez CShell

Consultez également le `ScriptEngine 'dans Roslyn qui provient de Microsoft, mais il s’agit uniquement du CTP.

Comme certains l'ont déjà mentionné, CS-Script existe également depuis un certain temps.

0
lukebuehler

Je n'ai pas encore essayé mais ça a l'air plutôt cool:

http://www.codeplex.com/scriptdotnet

0
mattlant