如何解决获取有关Func <T>委托的调用方和参数名称和值的信息
我有一个暴露公开方法的类(ExecuteJob),该方法接受Func委托并异步运行。我需要了解以下信息:
示例代码
public static class JobHandlerManager
{
public static async Task ExecuteJob<T>(Func<T> MetodoDaEseguire)
{
Params parOfMethod = MetodoDaEseguire.getmethodParams();
// here I need to get info about above points
string Caller = "ExternalMethod"
string Parameters = "\"par1\" = \"a\",\"par2\" = 10,\"par3\" = [\"x\",\"y\",\"z\"] "
int JobID = CalculateJobId();
parOfMethod = parOfMetho.add(JobID);
Func<T> NewMethod = MetodoDaEseguire(parOfMethod);
Task.Run(MetodoDaEseguire);
}
}
public void DoStuff(string par1,int par 2,string[] arraypar,int JobID)
{
// JobID is set by JobHandlerManager.ExecuteJob
}
public void ExternalMethod()
{
JobHandlerManager.ExecuteJob(() => DoStuff("a",10,new string[] {"x","y","z"}));
}
解决方法
在所提供的情况下,您可以使用expression trees和CallerMemberNameAttribute
至少实现其中的一部分:
public static int DoStuff(string par1,int par2,string[] arraypar,int JobID)
{
// JobID is set by JobHandlerManager.ExecuteJob
return 1;
}
public static void ExternalMethod()
{
JobHandlerManager.ExecuteJob(() => DoStuff("a",10,new string[] { "x","y","z" },1));
}
public static class JobHandlerManager
{
public static T ExecuteJob<T>(Expression<Func<T>> MetodoDaEseguire,[CallerMemberName]string caller = "")
{
Console.WriteLine(caller); // will print "ExternalMethod"
var mc = MetodoDaEseguire.Body as MethodCallExpression;
Console.WriteLine(string.Join(",",mc.Method.GetParameters().Select(p => p.Name))); // will print "par1,par2,arraypar,JobID"
Console.WriteLine(string.Join(",mc.Arguments)); // will print ""a",new [] {"x","z"},1"
return MetodoDaEseguire.Compile()();
}
}
然后呼叫ExternalMethod();
将显示:
ExternalMethod
par1,JobID
"a",1
但是要提防性能和闭包(即要从局部变量,字段等传递实际值,还需要做更多的工作)。
要获取呼叫者类,您可以尝试例如查看Environment.StackTrace
或CallerFilePathAttribute
(取决于您的需求)。
UPD
要替换某些参数,您可以执行以下操作:
var newArgs = mc.Arguments.ToList();
var ardIdToReplace = newArgs.Count - 1; // find somehow index of replaced argument
newArgs[ardIdToReplace] = Expression.Constant(42);
var newLambda = Expression.Lambda<Func<T>>(Expression.Call(mc.Method,newArgs));
return newLambda.Compile()();
请记住,由于对表达式的自定义处理,这也很容易导致错误,导致您失去很多编译时的安全性(用户可以传递更多的代码,而我的解决方案可以支持)。
,我自己找到了最后一个问题的解决方案,包括在静态类中的这两个方法。
private static object GetArgumentValue(Expression element)
{
if (element is ConstantExpression)
{
return (element as ConstantExpression).Value;
}
var l = Expression.Lambda(Expression.Convert(element,element.Type));
return l.Compile().DynamicInvoke();
}
private static string[] GetParamArgumentsValue(ReadOnlyCollection<Expression> Arguments)
{
List<string> ParamArgumentsValue = new List<string>();
foreach (var arg in Arguments)
{
ParamArgumentsValue.Add(JsonConvert.SerializeObject(GetArgumentValue(arg)));
}
return ParamArgumentsValue.ToArray();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。