什么是最好的脚本语言embedded在C#桌面应用程序?
我们正在编写一个复杂的丰富的桌面应用程序,需要提供报告格式的灵活性,所以我们认为我们只是将我们的对象模型暴露给脚本语言。 那时候意味着VBA(这仍然是一个选项),但是pipe理的代码派生VSTA(我认为)似乎已经枯萎了。
现在什么是Windows .NET上的embedded式脚本语言的最佳select?
我已经用CSScript的惊人的结果。 这真的减less了在我的脚本应用程序中绑定和其他低级别的东西。
就个人而言,我会使用C#作为脚本语言。 .NET框架(以及Mono,感谢Matthew Scharley)实际上在框架中包含了每种.NET语言的编译器。
基本上,这个系统的实现有两个部分。
-
允许用户编译代码这是相对容易的,只需要几行代码就可以完成(尽pipe你可能想添加一个错误对话框,这可能是几十行代码,这取决于可用的方式你想要它)。
-
创build和使用编译后的程序集中包含的类这比上一步更困难(需要一点reflection)。 基本上,你应该把编译好的程序集作为程序的“插件”。 有很多关于如何在C#中创build插件系统的教程(Google是你的朋友)。
我已经实现了一个“快速”应用程序来演示如何实现这个系统(包括2个工作脚本!)。 这是应用程序的完整代码,只需创build一个新代码并将代码粘贴到“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 } } } } } } }
IronPython 。 以下是如何embedded它的概述。
PowerShell引擎被devise为可以轻松embedded到应用程序中以使其可以编写脚本。 实际上,PowerShell CLI只是引擎的基于文本的界面。
嘘语。
我select的脚本语言是Lua 。 它规模小,速度快,干净,logging完整,支持力度好,拥有一个非常好的社区 ,许多业内大公司(Adobe,暴雪,EA Games)都在使用,值得一试。
要在.NET语言中使用它, LuaInterface项目将提供您所需要的一切。
为什么不尝试C#? 单声道有一个伟大的新项目,特别是dynamic评估C#的:
IronRuby如上所述。 对于我来说,作为C#程序员的一个有趣的项目是Mono中的C#Eval支持 。 但目前尚不可用(将成为Mono 2.2的一部分)。
另一个投票IronPython。 embedded它很简单,与.Net类互操作很简单,而且,它是Python。
我havnt尝试过,但它看起来很酷:
JScript.NET是一个很好的。 小提琴手使用它。
我可能会build议我现在维护的S# 。 这是一个开源项目,用C#编写,专为.NET应用程序devise。
最初(2007 – 2009年),它在http://www.codeplex.com/scriptdotnet ,但最近它被转移到github。
试试Ela 。 这是一个类似于Haskell的函数式语言,可以embedded到任何.Net应用程序中。 即使它有简单但可用的IDE。
我刚刚为一个客户端创build了一个插件,允许他们用像VBA一样的模块编写C#代码。
我以前用过Lua 。 在Delphi应用程序,但它可以embedded到很多东西。 它用在Adobe的Photoshop Lightroom中 。
我喜欢用C#本身的脚本 。 现在,在2013年,对C#脚本的支持相当不错,越来越多的库可用。
Mono对脚本C#代码有很好的支持,你可以在你的应用程序中使用Mono.CSharp.dll
。 对于我已经使用的C#脚本应用程序来检查CShell
另外请查看来自Microsoft的Roslyn中的`ScriptEngine',但这只是CTP。
正如一些人已经提到的那样, CS-Script也出现了很长一段时间。