有没有办法获取传递给方法的参数数组?

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#版本的参数,以便我可以验证正确的参数是否传入按正确的顺序.

我只是想记录参数值和顺序,而不是它们的名字.

aqw*_*ert 7

如果使用Postsharp,则只需向要记录的方法添加属性即可.在此属性中,您可以编写日志记录代码,还将提供所需的参数.这被称为横切关注点和AOP(面向方面​​编程)


Yan*_*ton 5

我不确定访问调用堆栈的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)


Dav*_*son 0

这是我想出的解决方案:

PostSharp 或其他 AOP 解决方案在这种情况下并不实用,所以不幸的是我不得不放弃这个想法。

看来,虽然可以使用反射来参数名称和类型,但访问运行时值的唯一方法是附加调试器。

请参阅此处了解更多信息:

堆栈溢出

微软.public.dotnet.framework

因此,这仍然给我留下了大约 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)

然后可以将该块粘贴到方法的顶部以达到所需的效果。

它比我想要的更加手动,但它比手动输入参数要好得多,而且更不容易出错。