我有一个服务有很多不同的方法和很多参数。我已经创建了一个服务客户端,但是为所有可能的参数和功能创建 UI 会很痛苦,所以我每个方法只有一个按钮,并且代码配置了所有参数。它运行良好,但每次需要另一个参数时,都必须更改代码。所以我想,如果我有一个带有代码的文本框,它将被编译并即时调用,这将非常方便使用。所以我想要的是我有一个文本框,其中包含类似的代码ExecuteOperation1("a", "b", "c")
其中 ExecuteOperation 在我的表单类中定义。然后我可以轻松地动态更改参数。我试图搜索它是如何完成的,但所有示例都显示了使用命名空间和类等进行编译。有没有办法以某种方式在你的类中运行动态代码。当然,我的问题的另一个简单解决方案也值得赞赏。
2 回答
有几种不同的方式运行代码。一种不错的方法是使用 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 编译器可作为服务使用。我自己没有使用过这个,因为它处于技术预览阶段,我想要一些我现在可以部署的东西。尽管如此,它似乎有很多例子,其中一些是针对你想要的那种东西的。
如果看起来总是这样,ExecuteOperation1("a", "b", "c")
那么您可以使用反射来确定方法和参数名称。例如,以下代码为您提供了方法列表。MethodInfo.Invoke 可用于调用方法。
typeof(Service).GetMethods(BindingFlags.Public|BindingFlags.Instance);
这种方法不是很灵活,但相对容易理解并且不需要额外的库。