当前位置:  开发笔记 > 编程语言 > 正文

嵌入C#桌面应用程序的最佳脚本语言是什么?

如何解决《嵌入C#桌面应用程序的最佳脚本语言是什么?》经验,为你挑选了6个好方法。

我们正在编写一个复杂的富桌面应用程序,需要提供报表格式的灵活性,因此我们认为我们只需将对象模型公开给脚本语言.时间到了这意味着VBA(这仍然是一个选项),但托管代码衍生品VSTA(我认为)似乎已经枯萎了.

什么是Windows .NET上嵌入式脚本语言的最佳选择?



1> Grant Peters..:

就个人而言,我使用C#作为脚本语言..NET框架(和Mono,感谢Matthew Scharley)实际上包含了框架本身中每种.NET语言的编译器.

基本上,这个系统的实施有两个部分.

    允许用户编译代码这是相对简单的,只能在几行代码中完成(尽管你可能想要添加一个错误对话框,这可能是几十行代码,具体取决于可用的代码你希望它是).

    创建和使用已编译程序集中包含的类这比上一步要困难一些(需要一点点反射).基本上,您应该将编译的程序集视为程序的"插件".有很多关于用C#创建插件系统的方法的教程(谷歌是你的朋友).

我已经实现了一个"快速"应用程序来演示如何实现这个系统(包括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
                        }
                    }
                }
            }
        }
    }
}


仅供参考,对于其他任何好奇的人来说,是的,这确实可以在Mono上编译和运行.只需要编译部件的系统参考.
@Lavinski如果您不希望它污染您的AppDomain,那么只需创建一个新的(这可能是个好主意,因此您可以在"脚本"上设置更严格的安全性)
你知道这是否也适用于Mono,或者只能在.NET上使用?
这样做会污染AppDomain
@Lander - 非常轻巧.上面的代码是一个支持"脚本"的整个程序.`csscript.net`看起来像是某种包装器.这基本上是一个简单的实现.我认为一个更好的问题是"csscript.net为我做了什么,这不是".我不知道csscript在做什么,但他们肯定知道上面的代码在这里做了什么,他们在他们的库中有它(或者非常类似的东西).
@selkathguy是的,命名空间只是为了保持代码清洁,并帮助人们阅读它的清晰度.AFAIK,没有办法真正限制他们有权访问哪些名称空间,只能限制他们有权访问的程序集.你可以随时制作一切,但你想要暴露私人/内部的东西(尽管他们仍然可以通过反射获得它).如果你想要一个完全安全的环境,你必须严格限制他们使用的程序集,并将它们放在自己的AppDomain中(每个脚本可能是一个单独的程序,因此脚本不能与其他脚本混淆).

2> Ben Hoffstei..:

IronPython.以下是如何嵌入它的概述.



3> Hector Sosa ..:

我使用CSScript获得了惊人的效果.它真的减少了必须在我的脚本应用程序中进行绑定和其他低级别的东西.



4> Rodrick Chap..:

PowerShell引擎旨在轻松嵌入到应用程序中,以使其可编写脚本.实际上,PowerShell CLI只是引擎的基于文本的界面.

编辑:请参阅http://blogs.msdn.com/powershell/archive/2007/08/29/making-applications-scriptable-via-powershell.aspx



5> jop..:

嘘语.



6> Remo.D..:

我最喜欢的脚本语言是Lua.它小巧,快速,干净,完整记录,得到很好的支持,拥有一个很棒的社区,它被业内许多大公司(Adobe,Blizzard,EA Games)使用,非常值得一试.

要将它与.NET语言一起使用,LuaInterface项目将提供您所需要的一切.

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有