web-dev-qa-db-ja.com

C#デスクトップアプリケーションに埋め込むのに最適なスクリプト言語は何ですか?

複雑でリッチなデスクトップアプリケーションを作成しており、レポート形式の柔軟性を提供する必要があるため、オブジェクトモデルをスクリプト言語に公開するだけだと考えました。当時はVBAを意味していました(これはまだオプションです)が、マネージコードの派生VSTA(私は思う)はVineで枯れたようです。

Windows .NETの埋め込みスクリプト言語に最適な選択肢は何ですか?

97
Ewan Makepeace

CSScript を使用しましたが、驚くべき結果が得られました。スクリプト可能なアプリでバインディングやその他の低レベルのものを実行する必要が本当に減りました。

21
Hector Sosa Jr

個人的には、スクリプト言語としてC#を使用します。 .NETフレームワーク(およびMono、ありがとうMatthew Scharley)には、実際にはフレームワーク自体に各.NET言語のコンパイラが含まれています。

基本的に、このシステムの実装には2つの部分があります。

  1. ユーザーがコードをコンパイルできるようにするこれは比較的簡単で、数行のコードで実行できます(ただし、使用可能性に応じて、おそらく数十行のエラーダイアログを追加することもできます)あなたがそれをしたい)。

  2. コンパイルされたアセンブリに含まれるクラスを作成して使用するこれは、前の手順よりも少し難しくなります(わずかなリフレクションが必要です)。基本的に、コンパイルされたアセンブリをプログラムの「プラグイン」として扱う必要があります。 C#でプラグインシステムを作成するさまざまな方法に関するチュートリアルが多数あります(Googleはあなたの友人です)。

このシステムを実装する方法を示すために、「クイック」アプリケーションを実装しました(2つの作業スクリプトが含まれています!)。これはアプリケーションの完全なコードです。新しいコードを作成して、「program.cs」ファイルに貼り付けてください。この時点で、貼り付けようとしているコードの大部分を謝罪する必要があります(あまり大きくするつもりはありませんでしたが、コメントに少し夢中になりました)


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埋め込み方法 の概要を次に示します。

36
Ben Hoffstein

PowerShellエンジンは、アプリケーションに簡単に埋め込み、スクリプト化できるように設計されました。実際、PowerShell CLIはエンジンへの単なるテキストベースのインターフェイスです。

編集: https://devblogs.Microsoft.com/powershell/making-applications-scriptable-via-powershell/ を参照してください

19
Rodrick Chapman

ブー 言語。

13
jop

私が選んだスクリプト言語は Lua 最近です。小さく、高速で、クリーンで、完全に文書化され、十分にサポートされており、素晴らしい community 、多くの大企業で industry (Adobe、Blizzard、EA Games)で使用されています。間違いなく試してみる価値があります。

.NET言語で使用するには、 LuaInterface プロジェクトが必要なすべてを提供します。

8
Remo.D

C#を試してみませんか? Monoには特にC#を動的に評価するための素晴らしい新しいプロジェクトがあります:

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

3
DAC

前述のIronRuby。 C#プログラマとしての私にとって興味深いプロジェクトは、 MonoでのC#Evalサポート です。しかし、まだ利用できません(Mono 2.2の一部になります)。

2
Borek Bernard

IronPythonへの別の投票。埋め込みは簡単で、.Netクラスとの相互運用は簡単です。まあ、それはPythonです。

2
Robert Rossney

Ela を試してください。これはHaskellに似た関数型言語であり、.Netアプリケーションに 埋め込み を使用できます。シンプルでありながら使いやすいIDEでもあります。

S# をお勧めしますが、現在これを維持しています。これは、C#で記述され、.NETアプリケーション用に設計されたオープンソースプロジェクトです。

当初(2007-2009)は http://www.codeplex.com/scriptdotnet でホストされていましたが、最近はgithubに移動されました。

1
Peter

JScript.NETは良いものです。 Fiddler はそれを使用します。

1
Mark Cidade

クライアント用のプラグインを作成したところ、VBAがOfficeで行うように動作するモジュールでC#コードを記述できるようになりました。

0
Mark

以前に Lua を使用しました。 Delphiアプリで使用できますが、多くのものに埋め込むことができます。 AdobeのPhotoshop Lightroom で使用されています。

0
Tony

C#自体を使用したスクリプト作成が好きです。さて、2013年には、C#スクリプトのサポートが非常に良好になり、そのライブラリがますます利用可能になります。

Monoは script C#code を強力にサポートしており、アプリケーションにMono.CSharp.dllを含めるだけで.NETで使用できます。私が作成したC#スクリプトアプリケーションの場合 CShell

また、Microsoftによる Roslyn の「ScriptEngine」も確認してください。ただし、これはCTPのみです。

一部の人々がすでに言及したように、 CS-Script もかなり前から存在しています。

0
lukebuehler

私はまだこれを試しましたが、かなりクールに見えます:

http://www.codeplex.com/scriptdotnet

0
mattlant