c# - 动态生成一个 Action

标签 c# .net expression-trees

我正在尝试弄清楚如何在运行时动态创建一个 Action,但效果不佳。

假设我想调用一个方法并传入一个动态创建的 Action,这样我就可以跟踪该 Action 是否已被调用等(无论出于何种原因)。

void DoSomething(Action<string> action);

这就是我要调用的方法,我想以某种方式动态构建一个满足参数的 Action。

我知道我可以使用 new Action<string>((s) => { }); 构建一个

但对于这种情况,我在编译时不知道 Action 的签名,我想要的只是一个 super 通用的 Action,如果它被调用,它会让我知道。

这是项目通信系统的一部分,我希望能够支持可用的操作(想想 OnCompleted 回调)。

Proxy.DoSomething((s) => Console.WriteLine("The server said: " + s);

我希望能够生成一个表示,通过网络发送,在服务器上动态创建一个 Action ,调用对象上的方法并传入我的动态 Action ,将结果发送回客户端并调用那里有实际 Action 。

一点澄清:

客户端:

var proxy = GetProxyObject(); // Comms proxy
proxy.DoSomething((reply) => Console.WriteLine("Server said: " + reply));

下面:

  1. 发现 Action 的签名
  2. 构建一个内部表示对象(足够简单)
  3. 通过网络将其发送到服务器

服务器端:

void ReceivedMessage(msg)
{
   var actParam = msg.Parameters[0]; // This is obviously just for demonstration
   var action = BuildActionWrapper(actParam);
   var result = target.InvokeMethod("DoSomething", action.UnderlyingAction);

   // Send result and Action result back to client
   ReplyToClient(...);
}

void DoSomething(Action<string> act)
{
   act("HELLO!");
}

然后返回到客户端,将参数传递到服务器上动态生成的操作中,真正的操作将被这些参数调用。

最佳答案

这是一个如何构建这样的表达式树的示例:

var mi = typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null);
var parameter = Expression.Parameter(typeof(string));
var body = Expression.Call(null, mi, new[] { parameter });
Expression<Action<string>> expression = Expression.Lambda<Action<string>>(body, new[] { parameter });

expression.Compile()("test");

作为替代方案,您可以使用 Reflection.Emit在运行时生成委托(delegate)。

例如:

var dynMethod = new DynamicMethod("", null, new[] { typeof(string) });
var il = dynMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
var mi = typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null);
il.Emit(OpCodes.Call, mi);
il.Emit(OpCodes.Ret);

var dynDelegate = (Action<string>)dynMethod.CreateDelegate(typeof(Action<string>));
dynDelegate("test");

这将生成以下委托(delegate):

(string s) => Console.WriteLine(s)

关于c# - 动态生成一个 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14932481/

相关文章:

.net - RaisePropertyChanged 不起作用

c# - 使用哪个版本的 StringComparer

c# - 表达式树依赖分析器

c# - 使用表达式树构建 Func<int, double> 多项式

java - 我必须创建一个二元表达式树来存储 java 中的表达式 2 + 4 - 3

c# - XDocument 保存删除节点前缀

c# - 如何在具有通用接口(interface)和继承的 C# 中使用 "where"关键字

c# - PredicateBuilder 剥离括号,打破嵌套的 AND 与 OR 的组合

C# 使用多个参数启动应用程序

C# 字符无法正确计数(算法)