Dav*_*son 26 c# reflection methods arguments
说我有一个方法:
public void SomeMethod(String p1, String p2, int p3)
{
#if DEBUG
object[] args = GetArguments();
LogParamaters(args);
#endif
// Do Normal stuff in the method
}
Run Code Online (Sandbox Code Playgroud)
有没有办法检索传递给方法的参数数组,以便记录它们?
我有大量的方法,并希望避免手动将名称传递给记录器,因为人为错误将不可避免地蔓延.
我猜它会以某种形式涉及反射 - 这很好,因为它只会用于调试目的.
更新
更多信息:
我无法更改SomeMethod的方法签名,因为它作为WebMethod公开,并且必须复制它模拟的遗留系统.
遗留系统已经记录了传入的参数.从新实现开始将包装遗留系统,所以我希望记录进入C#版本的参数,以便我可以验证正确的参数是否传入按正确的顺序.
我只是想记录参数值和顺序,而不是它们的名字.
我不确定访问调用堆栈的API是否提供一种获取参数列表的方法。
但是,有一些方法可以注入IL来拦截方法调用和执行自定义代码。
我经常使用的库是Gael Fraiteur的PostSharp,它包含一个运行postbuild的应用程序,并根据您所使用的方面在您的输出程序集中注入IL。有一些属性可用来装饰程序集,类型或单个方法。例如:
[Serializable]
public sealed class LoggingAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs eventArgs)
{
Console.WriteLine("Entering {0} {1} {2}",
eventArgs.Method.ReflectedType.Name,
eventArgs.Method,
string.Join(", ", eventArgs.Arguments.ToArray()));
eventArgs.MethodExecutionTag = DateTime.Now.Ticks;
}
public override void OnExit(MethodExecutionArgs eventArgs)
{
long elapsedTicks = DateTime.Now.Ticks - (long) eventArgs.MethodExecutionTag;
TimeSpan ts = TimeSpan.FromTicks(elapsedTicks);
Console.WriteLine("Leaving {0} {1} after {2}ms",
eventArgs.Method.ReflectedType.Name,
eventArgs.Method,
ts.TotalMilliseconds);
}
}
Run Code Online (Sandbox Code Playgroud)
之后,您可以使用此属性装饰所需的方法:
[Logging]
public void SomeMethod(String p1, String p2, int p3)
{
//..
}
Run Code Online (Sandbox Code Playgroud)
这是我想出的解决方案:
PostSharp 或其他 AOP 解决方案在这种情况下并不实用,所以不幸的是我不得不放弃这个想法。
看来,虽然可以使用反射来参数名称和类型,但访问运行时值的唯一方法是附加调试器。
请参阅此处了解更多信息:
因此,这仍然给我留下了大约 50 个需要手动添加日志记录的方法的问题。
反思来拯救...
public String GetMethodParameterArray()
{
var output = new StringBuilder();
output.AppendLine();
Type t = typeof(API);
foreach (var mi in t.GetMethods())
{
var argsLine = new StringBuilder();
bool isFirst = true;
argsLine.Append("object[] args = {");
var args = mi.GetParameters();
foreach (var pi in args)
{
if (isFirst)
{
isFirst = false;
}
else
{
argsLine.Append(", ");
}
argsLine.AppendFormat("{0}", pi.Name);
}
argsLine.AppendLine("};"); //close object[] initialiser
output.AppendLine(argsLine.ToString());
output.AppendFormat("Log(\"{0}\",args);", mi.Name);
output.AppendLine();
output.AppendLine();
}
return output.ToString();
}
Run Code Online (Sandbox Code Playgroud)
此代码片段循环访问类上的方法,并输出一个使用传递到方法中的参数初始化的 object[] 数组以及包含参数和方法名称的 Log 调用。
输出示例:
object[] args = {username, password, name, startDate, endDate, cost};
Log("GetAwesomeData",args);
Run Code Online (Sandbox Code Playgroud)
然后可以将该块粘贴到方法的顶部以达到所需的效果。
它比我想要的更加手动,但它比手动输入参数要好得多,而且更不容易出错。
| 归档时间: |
|
| 查看次数: |
13868 次 |
| 最近记录: |