即时执行文本框中的代码

时间:2013-06-20 09:16:33

标签: c#

我的服务有很多不同的方法,有很多参数。我已经创建了一个服务客户端,但是为所有可能的参数和函数创建UI会非常麻烦,所以每个方法只有一个按钮,代码会配置所有参数。它运行良好,但每次需要其他参数时,都必须更改代码。所以我想如果我的文本框中包含的代码将被动态编译和调用,这将非常方便使用。所以我想要的是我有一个文本框,其代码类似ExecuteOperation1("a", "b", "c"),其中ExecuteOperation在我的表单类中定义。然后我可以轻松地动态更改参数。我试图搜索它是如何完成的,但所有示例都显示了使用命名空间和类等进行编译。有没有办法以某种方式在你的类中运行动态代码。我的问题的另一个简单的解决方案当然也很受欢迎。

2 个答案:

答案 0 :(得分:3)

有几种不同的方式可以动态运行代码。一个不错的方法是使用Microsoft提供的文件dynamic.cs available here(在LinqSamples \ DynamicQuery \ DynamicQuery下)。使用的一个例子是here

您还可以根据this article on MSDN自行手动构建表达式树。但是你需要编写一些解析代码才能做到这一点。

我已经使用了上述两种方法,我认为第一种方法对于您想要解决的问题似乎最有希望。例如,您可以将一些任意对象o作为表达式的参数,并包含其他对象,例如settings,这样用户就可以像在测试中一样编写o.ExecuteOperation1("a", "b", "c", settings)以下计划。

using System.Linq.Expressions;
using System.Linq.Dynamic;

// ...

public class Settings
{
    public int x;
}

public class Window
{
    public object ExecuteOperation1(string a, string b, string c, Settings s)
    {
        Console.WriteLine("{0}, {1}, {2}, {3}", a, b, c, s.x);
        return true;
    }
}

class Program
{
    static void Main(string[] args)
    {
        string strExpr = "o.ExecuteOperation1(\"a\", \"b\", \"c\", settings)";
        Window form = new Window();
        Settings s = new Settings();
        s.x = 42;

        Type retType = typeof(object);
        ParameterExpression[] paramExprs = new ParameterExpression[] { 
            Expression.Parameter(typeof(Window), "o"), 
            Expression.Parameter(typeof(Settings), "settings") };
        LambdaExpression Le = System.Linq.Dynamic.DynamicExpression.ParseLambda(
            paramExprs, retType, strExpr);
        Delegate compiledLe = Le.Compile();

        object result = compiledLe.DynamicInvoke(form, s);
        Console.WriteLine("Result is {0}", result.ToString());
    }
}

该程序输出

a, b, c, 42
Result is True

我必须在Dynamic.cs中注释掉第1137到1138行以使其工作(这些行排除了使用用户定义类型Window)。

最后,有Roslyn,它使.net编译器可用作服务。我自己没有使用它,因为它是在技术预览中,我想要一些我现在可以部署的东西。然而,似乎有很多例子,有些是针对那种你想要的东西。

答案 1 :(得分:0)

如果它总是看起来像ExecuteOperation1("a", "b", "c")那么您可以使用反射来确定方法和参数名称。例如,下面的代码为您提供了一个方法列表。 MethodInfo.Invoke可用于调用方法。

typeof(Service).GetMethods(BindingFlags.Public|BindingFlags.Instance);

这种方法不是很灵活,但相对容易理解,不需要额外的库。