简体   繁体   English

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

[英]Get name from variable in calling method - creating calling method signature, parameters and values

I'm looking for a way to get hold of the name of a variable that was passed into an extensionmethod. 我正在寻找一种方法来掌握传递到扩展方法中的变量的名称。 I want to have the name of the parameter in the calling variable. 我想在调用变量中包含参数的名称。 Sounds strange, let me explain. 听起来很奇怪,让我解释一下。

assume this piece of testing code 假设这段测试代码

    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");
        }
    }

On the last line you can see the exception being logged. 在最后一行,您可以看到正在记录的异常。 I want to be able to provide optional parameter support. 我希望能够提供可选的参数支持。 So the developers can add parameter information when needed. 因此,开发人员可以在需要时添加参数信息。

I've seen many posts about this on stackoverflow, lot's of different approaches. 我已经在stackoverflow上看到了很多关于此的帖子,有很多不同的方法。 Main thing is; 最主要的是 it can't be done fully generically. 它不能完全通用地完成。

Some code for explanation: 一些代码说明:

    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;
    }

Now, this testing code is getting the calling method name and it's parameters. 现在,此测试代码正在获取调用方法的名称及其参数。 That is, the names of the parameters. 即,参数的名称。 But not their values. 但不是他们的价值观。 The param.tostring() part only returns the type name. param.tostring()部分仅返回类型名称。 Not the value. 没有价值。 I've been reading on this and it seems this can't be done via reflection. 我一直在阅读,看来这不可能通过反思来完成。

So then I went for another approach, why not provide the parameters the developer finds suitable for logging. 因此,然后我尝试了另一种方法,为什么不提供开发人员认为适合记录的参数。 You don't need all of them most of the time anyway. 无论如何,您大部分时间都不需要它们。

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

So, this being a new testmethod, i'm providing the parameters of choice into the exception logging method. 因此,这是一种新的测试方法,我将选择的参数提供给异常日志记录方法。 But if you want to make this work, it's one hell of a job everytime to make this call. 但是,如果您想使此工作正常进行,那么每次进行此调用都是一件难事。

    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)
            });
        }
    }

Now this is working. 现在这正在工作。 But as said, i find the bottom part to cumbersome. 但是正如我所说,我发现底部很麻烦。 I was thinking along the lines of an extensionmethod, so I can shorten the creation of each kvp. 我一直在考虑一种扩展方法,因此可以缩短每个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);
    }
}

And this would then be used as 然后将其用作

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

This confronts me with the same issue I had before; 这使我面临与以前相同的问题。 the nameof(parameter), ofcourse, returns "parameter". 当然,nameof(parameter)返回“ parameter”。 I would also have to make a couple of extension methods for each type. 对于每种类型,我还必须制作几个扩展方法。 Or check for the type in the extension method to make sure i get the correct value. 或检查扩展方法中的类型,以确保获得正确的值。

So, in short: how can i get the name of this variable that invokes the extension method? 因此,简而言之:如何获得调用扩展方法的变量的名称?

You could do the following "hack". 您可以执行以下“ hack”。 Change the signature of your method to the following: 将方法的签名更改为以下内容:

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

And now your call site would look a little bit cleaner: 现在,您的呼叫站点看上去会更加干净:

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

And you can extract parameter info from the expressions the following way (using C# tuple support for convenience): 您可以通过以下方式从表达式中提取参数信息(为方便起见,使用C#元组支持):

private static (object Value, string ParamName) GetParameterInfo
    (Expression<Func<object>> expr)
{
    //First try to get a member expression directly.
    //If it fails we know there is a type conversion: parameter is not an object 
    //(or we have an invalid lambda that will make us crash)
    //Get the "to object" conversion unary expression operand and then 
    //get the member expression of that and we're set.
    var m = (expr.Body as MemberExpression) ??
            (expr.Body as UnaryExpression).Operand as MemberExpression;

    return (expr.Compile().Invoke(), m.Member.Name);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM