2016-06-30 2 views
1

테스트 API를 설계하고 있습니다. 내가 좋아하는 API를 갖고 싶어 :동적 매개 변수를 입력으로 사용하는 람다에서 속성 이름 가져 오기

// There is a dynamic object which should be tested to have certain properties. 
dynamic result = SomeMethod(); 

AssertPropertyIsNotNull(resut, o => o.Title); 
AssertPropertyIsNotNull(resut, o => o.City.Name); 

내가 속성을 주장 TestProperty 방법을 쓰고 싶어을하고 적절한 메시지를 표시 그것은처럼 실패 :이 예에서는 다음

private void AssertPropertyIsNotNull(dynamic result, Func<dynamic, object> propertySelector) 
{ 
    var propertyPath = GetPropertyPathFromFunc(propertySelector); 
    var errorMessage = $"{propertyPath} is not filled properly." 
    Assert.IsNotNull(propertySelector(result), errorMessage); 
} 

, I 시체가 GetPropertyPathFromFunc에 필요합니다.

질문 어떻게 입력으로 o => City.Name 같은 람다를 얻고 결과 "City.Name" 같은 문자열을 반환하는 방법을 쓸 수 있습니다.

+0

http://stackoverflow.com/questions/8215449/c-sharp-converting-lambda-expression-function-to-descriptive-string? – tire0011

답변

2

dynamic을 사용할 때 유형 안전성과 컴파일 타임 멤버 이름 검사를 느슨하게하므로 문자열을 속성 이름으로 사용하는 데 아무런 차이가 없습니다.

다음은 해결책입니다. 광범위한 오류 검사와 예외 처리가 필요합니다. 반사 오버 헤드를 줄이기 위해 캐싱 메커니즘을 추가 할 수도 있습니다. 언급 한 바와 같이

public static bool IsPropertyNull(dynamic obj, string propertyName) 
{ 
    var path = propertyName.Split('.'); 
    object tempObject = obj; 
    for (int i = 0; i < path.Length; i++) 
    { 
     PropertyInfo[] dynamicProperties = tempObject.GetType().GetProperties(); 
     var property = dynamicProperties.Single(x => x.Name == path[i]); 
     tempObject = property.GetValue(tempObject); 
    } 
    return tempObject == null; 
} 

bool isTitleNull = IsPropertyNull(result, "Title"); 
bool isCityNameNull = IsPropertyNull(result, "City.Name"); 
1

불행히도 dynamic 같이 현재 C# 컴파일러에 의해 구현 식 트리에 사용될 수 없다. 또는 액세스 한 속성 이름을 수집하는 사용자 지정 동적 개체를 사용하여 대리인을 호출 할 수 있습니다. 나는 이것을 아래에서 증명했다. 이것은 제한된 구문으로 만 작동하며, 더 복잡한 것을 처리하기 위해 많은 노력을 기울이지 않았습니다.

private static string GetPropertyPathFromFunc(Func<dynamic, object> propertySelector) 
{ 
    var collector = new PropertyNameCollector(); 
    propertySelector(collector); 
    return collector.Name; 
} 

private class PropertyNameCollector : DynamicObject 
{ 
    public string Name { get; private set; } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     if (!string.IsNullOrEmpty(Name)) 
      Name += "."; 
     Name += binder.Name; 
     result = this; 
     return true; 
    } 
} 
관련 문제