2011-01-06 6 views
8

나는 컴파일 타임에 유형을 알 수없는 객체 목록을 가지고 있습니다.일반 유형의 리플렉션을 사용하여 Count 속성을 얻는 방법

'Count'속성이있는 개체를 식별하고 값이 있으면 그 값을 가져와야합니다.

이 코드는 간단한 컬렉션 유형에 대해 작동합니다

PropertyInfo countProperty = objectValue.GetType().GetProperty("Count"); 
if (countProperty != null) 
{ 
    int count = (int)countProperty.GetValue(objectValue, null); 
} 

문제는이 같은 IDictionary<TKey,TValue>로, 일반적인 유형 작동하지 않는다는 것입니다. 이 경우 'Count'속성이 인스턴스화 된 객체에 있어도 'countProperty'값은 null로 반환됩니다.

내가 원하는 것은 컬렉션/사전 기반 개체를 식별하고 크기가있는 개체를 찾으면됩니다.

편집 : 요청에 따라, 여기이 간단한 컬렉션에서 확인을 작동하지만,하지 Dictionary<TKey,TValue>에서 파생 내가 가진 클래스에서 생성 된 객체에

private static void GetCacheCollectionValues(ref CacheItemInfo item, object cacheItemValue) 
{ 
    try 
     { 
     //look for a count property using reflection 
     PropertyInfo countProperty = cacheItemValue.GetType().GetProperty("Count"); 
     if (countProperty != null) 
     { 
      int count = (int)countProperty.GetValue(cacheItemValue, null); 
      item.Count = count; 
     } 
     else 
     { 
      //poke around for a 'values' property 
      PropertyInfo valuesProperty = cacheItemValue.GetType().GetProperty("Values"); 
      int valuesCount = -1; 
      if (valuesProperty != null) 
      { 
       object values = valuesProperty.GetValue(cacheItemValue, null); 
       if (values != null) 
       { 
        PropertyInfo valuesCountProperty = values.GetType().GetProperty("Count"); 
        if (countProperty != null) 
        { 
         valuesCount = (int)valuesCountProperty.GetValue(cacheItemValue, null); 
        } 
       } 
      } 
      if (valuesCount > -1) 
       item.Count = valuesCount; 
      else 
       item.Count = -1; 
     } 
    } 
    catch (Exception ex) 
    { 
     item.Count = -1; 
     item.Message = "Exception on 'Count':" + ex.Message; 
    } 
} 

작동하지 않는 코드의 전체 목록입니다 . 즉

CustomClass : 
    Dictionary<TKey,TValue> 

CacheItemInfo 캐시 항목에 대한 속성이 포함되어 단순한 클래스입니다 - 즉, 키, 계산, 유형, 만료 날짜

+0

('IDictionary '에 대한 생각은'GetType()'이 항상 * concrete * 타입을 반환 할 것이기 때문에 여기서는 도움이되지 않습니다. 무엇이든 가능하지만'Dictionary '입니다) –

+0

다음 코드는 그것은 여전히 ​​유효하지 않습니다. –

+0

그래서 대답은 반사를 무시하고 인터페이스로 전송하는 것이 었습니다. 아래의 정답을 참조하십시오. –

답변

11

이것은을 가지고 당신이, ICollection에 캐스팅되어 시도해야 우선 아주 싼 .Count :

ICollection col = objectValue as ICollection; 
if(col != null) return col.Count; 

하지만 작동합니다 사전에 대한 Count - 나는 Dictionary<,>으로이 테스트를했는데 잘 작동 -하지만주의 그 뭔가가 0123을 구현하는 경우에도은 (GetType()를 통해 반환)을 콘크리트 유형 하지 않습니다는 공개 API에 .Count이 있어야 - 그것은 하지public int Count {get;}을하면서 인터페이스를 충족하기 위해 명시 적 인터페이스 구현를 사용할 수 있습니다. 내가 말했듯이, Dictionary<,>에서 작동하지만 모든 유형에 대해 반드시 그런 것은 아닙니다. 마지막 도랑 노력으로

은 모든 다른 실패했을 경우

IEnumerable enumerable = objectValue as IEnumerable; 
if(enumerable != null) 
{ 
    int count = 0; 
    foreach(object val in enumerable) count++; 
    return count; 
} 

편집 주석에서 제기 된 Dictionary<,> 문제로보고 :

using System; 
using System.Collections; 
using System.Collections.Generic; 
public class CustomClass : Dictionary<int, int> { } 
public class CacheItemInfo 
{ 
    public int Count { get; set; } 
    public string Message { get; set; } 
} 
class Program { 
    public static void Main() { 
     var cii = new CacheItemInfo(); 
     var data = new CustomClass { { 1, 1 }, { 2, 2 }, { 3, 3 } }; 
     GetCacheCollectionValues(ref cii, data); 
     Console.WriteLine(cii.Count); // expect 3 
    } 
    private static void GetCacheCollectionValues(ref CacheItemInfo item, object cacheItemValue) 
    { 
     try 
     { 
      ICollection col; 
      IEnumerable enumerable; 
      if (cacheItemValue == null) 
      { 
       item.Count = -1; 
      } 
      else if ((col = cacheItemValue as ICollection) != null) 
      { 
       item.Count = col.Count; 
      } 
      else if ((enumerable = cacheItemValue as IEnumerable) != null) 
      { 
       int count = 0; 
       foreach (object val in enumerable) count++; 
       item.Count = count; 
      } 
      else 
      { 
       item.Count = -1; 
      } 
     } 
     catch (Exception ex) 
     { 
      item.Count = -1; 
      item.Message = "Exception on 'Count':" + ex.Message; 
     } 
    } 
} 
+0

마크 - 귀하의 기여에 감사드립니다.나는 내가 본 원래의 질문에서 중요한 세부 사항을 생략했다는 것을 발견했다. 내가 찾고있는 클래스 중 하나는 Dictionary 에서 파생되었으며 그 중 하나는 .Count()로 작동하지 않는 것이다. IDictionary <,>으로 테스트를 언급했는데 사용했던 코드를 게시 할 수 있습니까? –

+0

@Bruce -'Dictionary <,>'으로 테스트했는데 구체적인 유형 (인터페이스는'GetType()'과 직접적으로 관련이 없으며 하위 클래스와도 작동해야합니다. * 작동하지 않는 코드를 보여줄 수 있습니까? 방금 사전에 전달했습니다. –

+0

Marc - 지연에 대해 사과드립니다. 사용중인 전체 코드를 게시했으나 사전 항목과 함께 작동하지 않습니다. –

1

어떻게 먼저 확인 한 후이를 추가하는 방법에 대한 (! 안된!) ...

foreach (Type interfaceType in objectValue.GetType().GetInterfaces()) 
{ 
    countProperty = interfaceType.GetProperty("Count"); 
    //etc. 
} 
관련 문제