2010-04-05 7 views
1

I (단위 테스트에서 친숙한 오류 메시지를 생성하는 데 사용) 다음과 같은 방법이 있습니다(액션 <T>) .NAME이 예상 반환하지 않습니다 값

protected string MethodName<TTestedType>(Action<TTestedType> call) 
{ 
    return string.Format("{0}.{1}", typeof(TTestedType).FullName, call.Method.Name); 
} 

그러나 다음과 같이 내가 그것을 호출 할 때, 나는하지를 예상되는 결과를 얻을 수 :

var nm = MethodName<MyController>(ctrl => ctrl.Create()); 

를이 코드를 실행 한 후, nm"<Create_CreateShowsView>b__8", 그리고이 포함 "Create"을 (예상대로). 예상 결과를 얻기 위해 코드를 어떻게 변경해야합니까?

답변

7

Action 대신 Expression을 전달해야합니다. 나무가 어떻게 생겼는지 이해하면 실제로 표현식 트리를 사용하는 것은 그리 어렵지 않습니다. ON (왼쪽 c) 하나 개의 파라미터를 포함

(MyClass c) => c.TestMethod(); 

람다 식 (전체 블록) 등으로 세분화 될 수 있고, 및 본체 (c.TestMethod() :

코드 줄 우편).

"본문"은 특정 개체 (매개 변수 인 c), 실제 메서드 (TestMethod) 및 인수 집합 (이 경우에는 없습니다)에 대한 메서드 호출입니다.

시각 :

  LambdaExpression [ (MyClass c) => c.TestMethod() ] 
      /   \ 
      /   \ 
     /    \ 
     Parameters   Body [ MethodCallExpression: c.TestMethod() ] 
      |   / \ 
      |   / \ 
    1: MyClass c Object [c] \ 
           /\ 
          /\ 
          / \ 
      Method [TestMethod] Arguments [Empty] 

당신이 원하는 것은 람다 식의 몸 안에, 메소드 호출 식 내부 메소드 이름입니다. 그래서이 얻을 수있는 코드는 다음과 같습니다 전달 된 Expression<Action<T>> 정품 메서드 호출 표현 인 경우

물론
static string GetInnerMethodName<T>(Expression<Action<T>> expr) 
{ 
    MethodCallExpression mce = expr.Body as MethodCallExpression; 
    return (mce != null) ? mce.Method.Name : null; 
} 

이에만 작동합니다; 이 메서드의 소비자는 기술적으로 어떤 표현식도 전달할 수 있습니다.이 경우 null이 반환됩니다. 대신 예외를 던지거나, 기본값을 반환하거나, 적절하다고 생각되는 다른 동작을 수행하도록이 값을 조정할 수 있습니다.

이를 사용하는 특별한 작업을 수행 할 필요가 없습니다 - 그것은 원래의 메소드와 같은 사용의 :

string methodName = GetInnerMethodName<MyClass>(c => c.TestMethod()); 
+0

대단히 감사합니다. =) –

0

b__8 것은 λ에 대해 C# 컴파일러가 생성하는 메서드의 이름입니다. 예를 들어, Reflector을 사용하여이를 볼 수 있습니다.

"만들기"라고 말하면 실제로는 Create이라는 메서드를 만들어야합니다. 물론 Action에 맞아야하므로 void을 반환해야합니다. 간단한 경우


, 당신은 호출 할 방법을 나타내는 문자열을 사용하는 방법을 만들고, 지정된 형식의 개체에 메소드를 호출하는 조치를 반환 할 수 있습니다. 예를 들어 this tutorial을 참조하십시오.

+0

확인을 클릭합니다. 메소드의 CLR 이름 대신 *에서 * 이름을 선택할 수있는 방법이 있습니까? –

+0

@Tomas : 익명 함수이므로 이름이 없습니다.이 메소드는 실제로'Create'가 아니며, 'TTestedType'을 매개 변수로 사용하고'Create' 메소드를 호출하는 무명 메소드입니다. " – Aaronaught

+0

@Aaron - 당신 말이 맞아요. 그것은 내가 간과했던 것입니다 ... 그 익명의 방법으로 "창조"할 수있는 방법이 있습니까? –

관련 문제