Search code examples
c#lambdac#-6.0nameof

Is it possible to get the original parameter name using nameof() in a lambda expression?


I need to create a CSV style string of parameters mapped to their values. For example:

static void MyMethod(int i, string str, object obj, bool flag)
{
    string example = "i=123,str=Hello,obj=1.0,flag=false";
}

Called like:

MyMethod(123, "Hello", 1.0, false);

I would want an output like the string example.

I need to do this for a large number of methods which have many different signatures and may not use all parameters in each method with no discernible pattern - so I have tried to create a method to automate the process somewhat.

I have attempted to solve this using a delegate and nameof:

delegate string GetParametersDelegate(params object[] parameters);

static GetParametersDelegate GetParametersFunc = (parameters) =>
{
    return string.Join(",", parameters
        .Select(parameter => nameof(parameter) + "=" + parameter));
};

Called like:

static void MyMethod(int i, string str, object obj, bool flag)
{
    string notTheResultIWant = GetParameters(i, str, obj, flag);
    // notTheResultIWant = "parameter=123,parameter=Hello,parameter=1.0,parameter=false"
}

I have found this results in the name of the variable in the lambda being used instead of the original parameter name - so every value is incorrectly mapped to parameter from the lambda.

Is what I'm trying to do even possible to achieve? Or is there another way I can approach this problem?


Solution

  • One solution I came up with is getting ParameterInfo[] of called method via its MethodInfo:

    delegate string GetParametersDelegate(Delegate method, params object[] parameters);
    
    static GetParametersDelegate GetParametersFunc = (method, parameters) =>
    {
        var paramNames = method.Method.GetParameters().Select(pInfo => pInfo.Name);
        return
            paramNames.Select((name, index) => $"{name}={parameters[index]?.ToString() ?? "null"}")
                .Aggregate((a, b) => $"{a},{b}");
    };
    

    You can call:

    static void MyMethod(int i, string str, object obj, bool flag)
    {
        var method = (Action<int, string, object, bool>)MyMethod;
        var notTheResultIWant = GetParametersFunc(method, i, str, obj, flag);
    }