将用户脚本引擎添加到我的应用程序

时间:2016-04-18 20:14:16

标签: c# asp.net-mvc vb.net

我见过几个允许用户通过vb-script或javascript添加自定义的应用程序。一个重要的例子是通过vbscript的办公室插件或带有ruby脚本的RPG制造商。

我想在我的某个应用中添加该选项,让用户使用某些脚本语言编写一些自定义规则,每次运行时都会运行并保存/提交网页

我知道这个问题有点深,但在谷歌上花了大约一个小时后我仍然不知道从哪里开始解决这类问题。我知道在尝试这个时需要考虑很多。

请指出正确的方向。

2 个答案:

答案 0 :(得分:3)

根据您要支持的语言,有几种选择。 VB脚本可以使用MSScriptControl完成,C#可以使用Microsoft.CSharp完成。

这是我刚刚从数据库中提取C#脚本并执行它的一个简单示例。请注意,这只接受字符串,因此如果您希望参数是集合或不同的数据类型,则必须调整它。

value = CreateTransformMethodInfo(_script.ScriptBody).Invoke(null, args.Select(x => x.Value).ToArray()); //args would be the arguments in your script

public static MethodInfo CreateTransformMethodInfo(string script)
    {
        using (var compiler = new CSharpCodeProvider())
        {
            var parms = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true,
                CompilerOptions = "/optimize",
                ReferencedAssemblies = { "System.Core.dll" }
            };

            return compiler.CompileAssemblyFromSource(parms, script)
                .CompiledAssembly.GetType("Transform")
                .GetMethod("Execute");
        }
    }

然后实际的脚本如下所示:

public class Transform
{
    public static string Execute(string firstName)
    {
        return "Test";
    }
}

对此的一个警告是,您需要命名类'Transform'和每次运行'Execute'的方法,因为您可以看到我们在编译要运行的方法时使用这两个值。你可以命名任何你想要的助手类或方法,只要'execution'类和方法保持Transform / Execute。

答案 1 :(得分:1)

如果您希望编码位于客户端,您可以使用Javascript轻松地eval(userCode)其中usercode是一个字符串。

如果您愿意使用c#在服务器端运行用户代码,则可以使用带有库Microsoft.CSharpSystem.CodeDom.Compiler的内置编译器。可以这样做:

string code = @"
    using System;

    namespace First
    {
        public class Program
        {
            public static void Main()
            {
            " +
                "Console.WriteLine(\"Hello, world!\");"
                + @"
            }
        }
    }
"; //Assume this is the code the client gave you
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();

parameters.GenerateInMemory = true; //You can add references to libraries using parameters.ReferencedAssemblies.Add(string - name of the assembly).

CompilerResults results = provider.CompileAssemblyFromSource(parameters, code); //Compiling the string to an assembly

if (results.Errors.HasErrors)
{
    StringBuilder sb = new StringBuilder();

    foreach (CompilerError error in results.Errors)
    {
        sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
    }

    throw new InvalidOperationException(sb.ToString());
} //Error checking

Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("First.Program"); //Getting the class object
MethodInfo main = program.GetMethod("Main"); //Getting the main method to invoke

main.Invoke(null, null); //Invoking the method. first null - because the method is static so there is no specific instance to run in, second null tells us there are no parameters.

代码段取自codeproject:http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime

希望它有所帮助!