문제

리플렉션을 사용하여 컬렉션을 반복하는 방법이 있습니까(바람직하게는 foreach를 통해)?리플렉션을 사용하여 개체의 속성을 반복하고 있으며 프로그램이 컬렉션 형식에 도달하면 컬렉션의 콘텐츠를 반복하고 컬렉션의 개체에 액세스할 수 있기를 바랍니다.

현재 모든 속성에 특성이 설정되어 있고 컬렉션인 속성에 IsCollection 플래그가 true로 설정되어 있습니다.내 코드는 이 플래그를 확인하고 그것이 true이면 리플렉션을 사용하여 유형을 가져옵니다.항목을 반복할 수 있도록 컬렉션에서 GetEnumerator 또는 Items를 호출하는 방법이 있습니까?

도움이 되었습니까?

해결책

이 문제가 있었지만 리플렉션을 사용하는 대신 IEnumerable인지 확인하게 되었습니다.모든 컬렉션이 이를 구현합니다.

if (item is IEnumerable)
{
    foreach (object o in (item as IEnumerable))
    {

    }
} else {
   // reflect over item
}

다른 팁

나는 Darren이 제안한 것과 유사한 기술을 사용하려고 시도했지만 컬렉션만이 IEnumerable을 구현하는 것이 아니라는 점에 유의하십시오. string 예를 들어 IEnumerable이기도 하며 문자를 반복합니다.

다음은 개체가 컬렉션인지 확인하는 데 사용하는 작은 함수입니다(ICollection도 IEnumerable이므로 열거 가능함).

    public bool isCollection(object o)
    {
        return typeof(ICollection).IsAssignableFrom(o.GetType())
            || typeof(ICollection<>).IsAssignableFrom(o.GetType());
    }

속성 값을 가져온 다음 IEnumerable로 캐스팅하면 됩니다.다음은 아이디어를 제공하는 (테스트되지 않은) 코드입니다.

ClassWithListProperty obj = new ClassWithListProperty();
obj.List.Add(1);
obj.List.Add(2);
obj.List.Add(3);

Type type = obj.GetType();
PropertyInfo listProperty = type.GetProperty("List", BindingFlags.Public);
IEnumerable listObject = (IEnumerable) listProperty.GetValue(obj, null);

foreach (int i in listObject)
    Console.Write(i); // should print out 123

당신이 할 수 있는 최선의 방법은 객체가 특정 컬렉션 인터페이스를 구현하는지 확인하는 것입니다. 아마도 IEnumerable이 필요한 전부일 것입니다.그런 다음 개체에서 GetEnumerator()를 호출하고 IEnumerator.MoveNext() 및 IEnumerator.Current를 사용하여 컬렉션을 탐색하면 됩니다.

컬렉션이 해당 인터페이스를 구현하지 않는 경우에는 도움이 되지 않지만, 그렇다면 실제로는 컬렉션이 아니라고 생각합니다.

단지 정보로서 누군가에게 도움이 될 수도 있습니다.나는 중첩된 클래스와 다른 클래스의 컬렉션을 갖춘 클래스를 가졌습니다.클래스의 속성 값과 중첩 클래스 및 클래스 컬렉션을 저장하고 싶었습니다.내 코드는 다음과 같습니다.

 public void LogObject(object obj, int indent)
    {
        if (obj == null) return;
        string indentString = new string(' ', indent);
        Type objType = obj.GetType();
        PropertyInfo[] properties = objType.GetProperties();

        foreach (PropertyInfo property in properties)
        {
            Type tColl = typeof(ICollection<>);
            Type t = property.PropertyType;
            string name = property.Name;


            object propValue = property.GetValue(obj, null); 
            //check for nested classes as properties
            if (property.PropertyType.Assembly == objType.Assembly)
            {
                string _result = string.Format("{0}{1}:", indentString, property.Name);
                log.Info(_result);
                LogObject(propValue, indent + 2);
            }
            else
            {
                string _result = string.Format("{0}{1}: {2}", indentString, property.Name, propValue);
                log.Info(_result);
            }

            //check for collection
            if (t.IsGenericType && tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) ||
                t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl))
            {
                //var get = property.GetGetMethod();
                IEnumerable listObject = (IEnumerable)property.GetValue(obj, null);
                if (listObject != null)
                {
                    foreach (object o in listObject)
                    {
                        LogObject(o, indent + 2);
                    }
                }
            }
        }
    }

이 함수를 호출했습니다.

LogObject(obj, 0);

그러나 내 클래스 내에 일부 구조체가 있으므로 해당 값을 가져오는 방법을 알아내야 합니다.게다가 목록이 좀 있어요.그 가치도 알아내야 하는데....코드를 업데이트하면 게시하겠습니다.

리플렉션을 사용할 때 반드시 해당 개체의 인스턴스를 사용할 필요는 없습니다.개체의 속성을 반복하려면 해당 유형의 인스턴스를 만들어야 합니다.따라서 리플렉션을 사용하는 경우 ConstructorInfo.Invoke() (?) 메서드를 사용하여 새 인스턴스를 만들거나 해당 유형의 인스턴스를 가리킵니다.

Type.FindInterfaces 메서드를 살펴보겠습니다.이는 특정 유형으로 구현된 인터페이스를 필터링할 수 있습니다.PropertyInfo.PropertyType.FindInterfaces(filterMethod, filterObjects)에서와 같습니다.IEnumerable로 필터링하고 결과가 반환되는지 확인할 수 있습니다.MSDN에는 메소드 문서에 훌륭한 예가 있습니다.

객체의 인스턴스를 사용하지 않고 유형을 사용하는 경우 다음을 사용할 수 있습니다.

// type is IEnumerable
if (type.GetInterface("IEnumerable") != null)
{
}

다소 간단한 접근 방식은 개체를 컬렉션으로 형식 변환하여 직접 사용하는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top