我需要构建一个跟踪,可以记录Action
代码变量中传递的所有参数。
如果动作变量填充了lambda表达式,如何从Action实例中获取所有参数?
更新(澄清行动对象的使用)
我在我试图构建的API跟踪器下面发布。 API跟踪器需要从操作对象中传递的lambda表达式中获取参数:
public static class Tracer
{
public static void log(Action action)
{
// note that action will always be set with a lambda function. See ServiceProxy class bellow.
//..grab the action parameters and name and log them
}
}
我只找到了从表达式中获取这些信息的方法。从动作类型对象,我没有找到它保存参数,只找到方法名称。
此Tracer将在公开服务的Proxy类中使用。应记录所有呼叫。 Proxy使用调用服务的函数包装器,如下所示:
class ServiceProxy:IServiceProxy {
...
private void CallWrapper(Action func)
{
try
{
Tracer.log(func);
func();
}
catch (Exception ex){...}
}
//method call example
public void IServiceProxy.RequestX(String p1, int p2){
CallWrapper(() => service.RequestX(p1, p2));//p1 and p2 parametersshould be logged by the Tracer.
}
}
为了重用CallWrapper
方法,lambda表达式签名必须是动态的,这意味着func
类型不能声明为泛型(例如:Action<String,Int>
)。< / p>
答案 0 :(得分:0)
您可以使用Linq.Expressions提取您的参数
这意味着您需要将null
更改为Action
Aftre这样做,你将能够通过自定义表达式访问者浏览你的lambda。
让我们首先添加一个可以检查表达式的新类:
Expression<Action>
现在我们可以在public class ArgumentExtractor : System.Linq.Expressions.ExpressionVisitor
{
private Dictionary<string, object> arguments;
public IDictionary<string, object> Arguments => arguments;
protected override Expression VisitMethodCall(MethodCallExpression node)
{
arguments = node.Arguments
.Select(a =>
{
var memeber = a as MemberExpression;
if (memeber == null)
return null;
var name = memeber.Member.Name;
var container = (memeber.Expression as ConstantExpression)?.Value;
var value = container.GetType().GetField(name).GetValue(container);
return new {name, value};
})
.Where(x => x != null)
.ToDictionary(x => x.name, x => x.value);
return base.VisitMethodCall(node);
}
}
:
Tracer
最后我们需要修改public static class Tracer
{
public static void log(Expression<Action> action)
{
var argumentExtractor = new ArgumentExtractor();
argumentExtractor.Visit(action);
var arguments = argumentExtractor.Arguments;
// to do: write it to log
}
}
:
CallWrapper
您可以找到完整的演示here