4

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

4

2 回答 2

3

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

您还可以按照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 编译器可作为服务使用。我自己没有使用过这个,因为它处于技术预览阶段,我想要一些我现在可以部署的东西。尽管如此,它似乎有很多例子,其中一些是针对你想要的那种东西的。

于 2013-06-20T10:40:16.300 回答
0

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

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

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

于 2013-06-20T11:02:09.743 回答