从调用方法中的变量中获取名称 - 创建调用方法签名,参数和值

时间:2017-12-07 17:09:53

标签: c# logging reflection extension-methods stack-trace

我正在寻找一种方法来获取传递给extensionmethod的变量的名称。我想在调用变量中有参数的名称。听起来很奇怪,让我解释一下。

假设这段测试代码

    private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
    {
        try
        {
            throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
        }
        catch (Exception ex)
        {
            GenericLog_Exception(ex, "it's on fire, please help");
        }
    }

在最后一行,您可以看到记录的异常。我希望能够提供可选的参数支持。因此,开发人员可以在需要时添加参数信息。

我在stackoverflow上看过很多关于这个的帖子,很多不同的方法。主要是;它不能完全一般地完成。

一些代码用于解释:

    static string GetCallingMethodSignature()
    {
        StackTrace stackTrace = new StackTrace();

        // Get calling method name
        var callingMethod = stackTrace.GetFrame(1).GetMethod();
        var callingMethod_Name = callingMethod.Name;

        // get calling method params
        string retVal = string.Empty;

        var callingMethod_Parameters = callingMethod.GetParameters();

        retVal = callingMethod_Name + "(";
        foreach (var param in callingMethod_Parameters)
        {
            retVal += param.Name + ": " + param.ToString() + ",";
        }
        retVal.Remove(retVal.Length - 1, 1);
        retVal += ")";

        return retVal;
    }

现在,这个测试代码正在获取调用方法名称及其参数。也就是参数的名称。但不是他们的价值观。 param.tostring()部分仅返回类型名称。不是价值。我一直在读这个,看来这不能通过反思来完成。

然后我又采用了另一种方法,为什么不提供开发人员认为适合记录的参数。无论如何,你大部分时间都不需要所有这些。

private static string GenericLog_Exception(Exception exceptionData, string extraInformation, params KeyValuePair<string, object>[] parameters)

所以,这是一种新的测试方法,我将选择的参数提供给异常日志记录方法。但是如果你想让这项工作成功,那么每次打电话都是一件好事。

    private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
    {
        try
        {
            throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
        }
        catch (Exception ex)
        {
            GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[]{
                new KeyValuePair<string, object>("firstParam", firstParam),
                new KeyValuePair<string, object>("secondParam", secondParam),
                new KeyValuePair<string, object>("thirdParam", thirdParam)
            });
        }
    }

现在这个有用了。但正如所说,我发现底部很麻烦。我正在考虑扩展方法,所以我可以缩短每个kvp的创建。

internal static class ExtensionMethodsForTesting
{
    internal static KeyValuePair<string, object> AsKeyValuePair(this string parameter)
    {
        var name = nameof(parameter);
        return new KeyValuePair<string, object>(name, parameter);
    }
}

然后将其用作

GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[] { firstParam.AsKeyValuePair() });

这使我面临同样的问题;名称(参数),ofcourse,返回“参数”。我还必须为每种类型制作几种扩展方法。或者检查扩展方法中的类型以确保我获得正确的值。

因此,简而言之:如何获取调用扩展方法的此变量的名称?

1 个答案:

答案 0 :(得分:1)

你可以做以下“黑客”。将方法的签名更改为以下内容:

    let pauser = SKAction.wait(forDuration: 3.0)
    let trigger = SKAction.perform(#selector(GameViewController.hideFunc, onTarget: self)
    let pauseThenTrigger = SKAction.sequence([ pauser, trigger ])
    let repeatForever = SKAction.repeatForever(pauseThenTrigger)
    node.run( repeatForever )

现在你的通话网站看起来会更清洁一点:

private static string GenericLog_Exception(
        Exception exceptionData, 
        string extraInformation, 
        params Expression<Func<object>>[] parameters)

您可以通过以下方式从表达式中提取参数信息(为方便起见,使用C#tuple支持):

GenericLog_Exception(ex, 
                     "it's on fire, please help",
                     () => firstParam,
                     () => secondParam,
                     () => thirdParam);