2010-05-10 6 views
1

배경는 IEnumerable <T> 및 반사

, 여기에 .NET 2.0에서 근무 일반적으로 목록을 반영. 원래는 통과하는 속성에 IEnumerable 인터페이스가 지원되는지 감지하기 위해 원래 t.IsAssignableFrom(typeof(IEnumerable))을 사용했습니다. (따라서 개체를 안전하게 캐스팅 할 수 있습니다.)

그러나 개체가 BindingList<T> 인 경우이 코드는 True으로 평가되지 않았습니다.

다음

나는 t.IsSubclassOf(typeof(IEnumerable))를 사용하는 시도하거나 운이 없었다.

코드

/// <summary> 
    /// Reflects an enumerable (not a list, bad name should be fixed later maybe?) 
    /// </summary> 
    /// <param name="o">The Object the property resides on.</param> 
    /// <param name="p">The Property We're reflecting on</param> 
    /// <param name="rla">The Attribute tagged to this property</param> 
    public void ReflectList(object o, PropertyInfo p, ReflectedListAttribute rla) 
    { 
     Type t = p.PropertyType; 
     //if (t.IsAssignableFrom(typeof(IEnumerable))) 
     if (t.IsSubclassOf(typeof(IEnumerable))) 
     { 
      IEnumerable e = p.GetValue(o, null) as IEnumerable; 

      int count = 0; 
      if (e != null) 
      { 
       foreach (object lo in e) 
       { 
        if (count >= rla.MaxRows) 
         break; 

        ReflectObject(lo, count); 

        count++; 
       } 
      } 
     } 
    } 

의도

나는 기본적으로 내가 ReflectedListAttribute 끝까지 반영하고있는 특성에이 함수를 호출 할 목록을 태그 할 수 있습니다. (이미 작동 중임)

일단이 함수 내부에 속성이있는 객체와 관련하여 PropertyInfo이 있으면 속성의 값을 가져 와서 IEnumerable로 캐스팅하고 (가능한 경우) 각 자식을 반복하고 count 변수를 가진 자식에 대해 ReflectObject(...)을 호출하십시오.

답변

11

as IEnumerable을 수행하고 변수가 null이 아니면 IEnumerable 인터페이스를 구현한다는 것을 알고 있습니다. 이 충분하다

Type t = p.PropertyType; 
//if (t.IsAssignableFrom(typeof(IEnumerable))) 
if (t.IsSubclassOf(typeof(IEnumerable))) 
{ 

: 왜 당신은 if 문에서 모든

public void ReflectList(object o, PropertyInfo p, ReflectedListAttribute rla) 
{ 
    IEnumerable e = p.GetValue(o, null) as IEnumerable; 

    int count = 0; 
    if (e != null) 
    { 
     foreach (object lo in e) 
     { 
      if (count >= rla.MaxRows) 
       break; 
      ReflectObject(lo, count); 
      count++; 
     } 
    } 
} 
+0

예전 코드를 조롱하고 작동하지 않을 때 이전 코드로 돌아 가면 이런 일이 발생합니다. 당신이 그것을 언급 했으므로 나는 그것을 놓쳤을 때 얼마나 안타까웠는지 모른다.> _ <. 감사합니다 – Aren

3

당신은하지는

는 코드가 필요?

이미 var e = ... as IEnumerable을 수행 한 후 null이 아닌지 확인하십시오.

충분하지 않습니까?

1

이러한 작업. :)

ListCollection입니다. 따라서 테스트는 다릅니다. Dictionary에는 2 개의 내부 컨테이너가 있습니다. 따라서 같은 테스트.

public static bool IsList(object obj) 
{ 
    System.Collections.IList list = obj as System.Collections.IList; 
    return list != null; 
} 

public static bool IsCollection(object obj) 
{ 
    System.Collections.ICollection coll = obj as System.Collections.ICollection; 
    return coll != null; 
} 

public static bool IsDictionary(object obj) 
{ 
    System.Collections.IDictionary dictionary = obj as System.Collections.IDictionary; 
    return dictionary != null; 
} 



사용 예 -

if (IsDictionary(fieldObject)) //key-value type collection? 
{ 
    System.Collections.IDictionary dictionary = fieldObject as System.Collections.IDictionary; 
    foreach (object _ob in dictionary.Values) 
    { 
     //do work 
    } 
    // dictionary.Clear(); 
} 
else //normal collection 
{ 
    if (IsCollection(fieldObject)) 
    { 
     System.Collections.ICollection coll = fieldObject as System.Collections.ICollection; 
     foreach (object _ob in coll) 
     { 
      //do work 
     } 

     if (IsList(fieldObject)) 
     { 
      //System.Collections.IList list = fieldObject as System.Collections.IList; 
      //list.Clear(); // <--- List's function, not Collection's. 
     } 
    } 
} 
+0

중복 패턴을 사용하므로 패턴을 사용하지 않는 것이 좋습니다. "as"를 사용한 후에 널 체크를 할 것으로 예상되며, 이것은 간단한 코드 (추가 메소드 호출이 필요 없음)와 단일 캐스트 (Jens 응답 참조)가됩니다. –

+0

나는 이해한다. 이들은 재사용 성 목적으로 게시 된 기능입니다. Jens 메서드는 코드를 계층화하여 단순화하지만 중복 영역도 제공합니다. OP가 지금 선택합니다. – Nayan

4

MSDN

IsSubclassOf 방법과는 인터페이스 다른 인터페이스에서 유래 여부를 결정 사용하거나 되든지 관계없이 수없는 클래스는를 구현합니다. 10 인터페이스는

또한 일지 어떨지의 구현이 잘못,이 같이 사용할 것을 목적으로 GetInterface 방법을 사용하여는 IEnumerable은 t에 의해 구현되는 경우

typeof(IEnumerable).IsAssignableFrom(t) 

이 사실 반환해야합니다 ..