2017-12-07 32 views
0

확장 메서드에 전달 된 변수의 이름을 얻는 방법을 찾고 있습니다. 호출하는 변수에 매개 변수의 이름을 지정하고 싶습니다. 이상하게 들리지만 설명하겠습니다. 호출 메서드의 변수에서 이름 가져 오기 - 호출 메서드 서명, 매개 변수 및 값 만들기

는 예외가 기록되는 것을 볼 수있는 마지막 줄에 테스트 코드

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

이것은 내가 전에했던 같은 문제로 날을 직면로 사용됩니다; nameof (매개 변수), ofcourse는 "매개 변수"를 반환합니다. 또한 각 유형에 대해 두 가지 확장 방법을 만들어야합니다. 또는 확장 메서드의 형식을 확인하여 올바른 값을 가져 왔는지 확인하십시오.

간단히 말해서 : 확장 메서드를 호출하는이 변수의 이름을 어떻게 얻을 수 있습니까?

+1

'[CallerMemberName] string propertyName = null'을 시도 했습니까? – Nekeniehl

+0

@Nekeniehl :이 경우 "TestingMethod"라는 호출 메서드 이름이 나타납니다. – Obelix

답변

1

다음과 같은 "해킹"을 할 수 있습니다. 사용 (

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

그리고 당신은 표현에서 다음과 같은 방법을 매개 변수 정보를 추출 할 수 있습니다 :

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

을 이제 통화 사이트는 조금 청소기를 보일 것이다 다음에 메소드의 서명을 변경 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); 
} 
+0

은 매력처럼 작동합니다! 매우 멋진 해결책. 나는 중간 부분에 대해 들어 본 적이없는이 하나에 뛰어 들어갈 것입니다. – Obelix

+0

@Obelix 도움이 된 것을 기쁘게 생각하며 중간 부분에 약간의 설명을 추가했습니다. – InBetween