簡體   English   中英

將IEnumerable轉換為IEnumerable <T>

[英]Convert / Cast IEnumerable to IEnumerable<T>

我有一個類(一個Web控件),它具有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});

雖然它並不理想......特別是,如果source不完全IEnumerable<type>那么調用將失敗。 例如,如果第一個元素恰好是一個字符串,但是source是一個List<object> ,那么你就會遇到問題。

您可能希望重構代碼以使用IEnumerable.Cast<T>

像這樣使用它:

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

使用.NET 4,您可以在將source傳遞給方法之前將sourcedynamic 這將導致在運行時解決正確的泛型重載,而不會出現任何丑陋的反射代碼:

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 });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM