IT이야기

IEnumerable을 IEnumerable로 변환/캐스트

cyworld 2021. 10. 6. 22:39
반응형

IEnumerable을 IEnumerable로 변환/캐스트


IEnumerable 형식의 속성이 있고 LINQ를 사용하여 매개 변수로 작업하려는 클래스(웹 컨트롤)가 있습니다.

컴파일 타임에 유형을 모르는 IEnumerable<T>에 대한 리플렉션을 통해 캐스트/변환/호출하는 방법이 있습니까?

Method void (IEnumerable source)
{
    var enumerator = source.GetEnumerator();

    if (enumerator.MoveNext())
    {
        var type = enumerator.Current.GetType();
        Method2<type>(source); // this doesn't work! I know!
    }
}

void Method2<T>(IEnumerable<T> source) {}

당신은 Method2그것이 어떤 유형이 되는지 정말로 신경쓰나요? 그렇지 않은 경우 다음을 호출할 수 있습니다 Cast<object>().

void Method (IEnumerable source)
{
    Method2(source.Cast<object>());
}

올바른 유형을 확실히 가져와야 하는 경우 리플렉션을 사용해야 합니다.

다음과 같은 것:

MethodInfo method = typeof(MyType).GetMethod("Method2");
MethodInfo generic = method.MakeGenericMethod(type);
generic.Invoke(this, new object[] {source});

소스가 아닌 경우, 특히 ... 이상적인 생각이 아니다 정확히IEnumerable<type>다음 호출이 실패합니다. 예를 들어, 첫 번째 요소가 문자열이지만 소스가 List<object>이면 문제가 발생합니다.


사용하기 위해 코드를 리팩토링하고 싶을 것입니다. IEnumerable.Cast<T>

다음과 같이 사용하십시오.

IEnumerable mySet = GetData();
var query = from x in mySet.Cast<int>()
            where x > 2
            select x;

.NET 4를 사용하면 메서드에 전달 source하기 dynamic전에 캐스트할 수 있습니다 . 이렇게 하면 추한 리플렉션 코드 없이 런타임에 올바른 일반 오버로드가 해결됩니다.

void Method(IEnumerable source)
{
    var enumerator = source.GetEnumerator();

    if (enumerator.MoveNext())
    {
        Method2((dynamic)source);
    }
}

Jon의 두 번째 솔루션과 마찬가지로 소스가 실제로 IEnumerable<T>. 일반 경우 다음 솔루션에서와 같이 IEnumerable올바른 IEnumerable<T>유형으로 변환하는 다른 메서드를 만들어야 합니다.

IEnumerable<T> Convert<T>(IEnumerable source, T firstItem)
{
    // Note: firstItem parameter is unused and is just for resolving type of T
    foreach(var item in source)
    {
        yield return (T)item;
    }
}

void Method(IEnumerable source)
{
    var enumerator = source.GetEnumerator();

    if (enumerator.MoveNext())
    {
        dynamic firstItem = enumerator.Current;
        dynamic typedEnumerable = Convert(source, firstItem);
        Method2(typedEnumerable);
    }
}

이것은 몇 년 후이지만 List<Object>문제를 해결했습니다 .

void Method(IEnumerable source)
{
    var enumerator = source.GetEnumerator();
    if (enumerator.MoveNext())
    {
        MethodInfo method = typeof(MyClass).GetMethod("Method2");
        MethodInfo generic;
        Type type = enumerator.Current.GetType();
        bool sameType = true;

        while (enumerator.MoveNext())
        {
            if (enumerator.Current.GetType() != type)
            {
                sameType = false;
                break;
            }
        }

        if (sameType)
            generic = method.MakeGenericMethod(type);
        else
            generic = method.MakeGenericMethod(typeof(object));

        generic.Invoke(this, new object[] { source });
    }
}

참조URL : https://stackoverflow.com/questions/812673/convert-cast-ienumerable-to-ienumerablet

반응형