我需要一个Linq IEnumerable<> .Cast(typeof(T))

时间:2014-03-01 15:07:57

标签: c# .net linq generics ienumerable

我正在查询数据结构,结果类型为IEnumerable<IEntry>IEntry是一个框架接口),每个条目都有一个Data属性(类型为object)对我来说。

我的代码如下所示:

var resultList = framework.QueryAllOfType(queryClause.Type)
                          .Select(e => e.Data)
                          .ToList();
deleagte.DynamicInvoke(new[]{resultList});

委托背后的方法看起来像这样:

void Foo (IEnumerable<SomeType> bar); // if queryClause.Type == typeof(SomeType)
void Foo (IEnumerable<OtherType> bar); // if queryClause.Type == typeof(OtherType)

我绝对肯定queryClause.Type匹配SomeType,当然,.NET框架不是; - )

不幸的是,这意味着resultList的类型为IEnumerable<object>,尽管其中的所有对象都是正确的类型,但我无法调用委托(例外:IEnumerable<object> cannot be converted into IEnumerable<SomeType>

我知道为什么会这样,但解决方案是什么?我需要的是:

.Select(e => e.Data).Cast(queryClause.Type).ToList()应返回IEnumerable<queryClause.Type>。在.NET框架中是否已存在这样的事情?有更好的解决方案吗?

重要:由于两个答案已经误解了我的意图,我不能将该类型用作通用参数,因为它仅在运行时已知。因此,所有Cast<...>()Select(e =e as ...)等都无效。

3 个答案:

答案 0 :(得分:1)

您可以使用反射调用Cast

var method = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(queryClause.Type);
IEnumerable<object> cSeq = (IEnumerable<object>)method.Invoke(null, new object[] { resultList });

deleagte.DynamicInvoke(new[]{ cSeq });

答案 1 :(得分:0)

尝试完成以下内容:

.ToList<IEntry>()

例如,如果您执行以下操作:

int [] text = {01,2,3,4,5};

List<string> list = text.Select(x => x.ToString()).ToList<string>();

答案 2 :(得分:0)

根据您的反馈并使用其他答案,我创建了一个ToListOfType()扩展方法,可以满足您的需求。

public static class EnumerableExtensions
{
    private static readonly Type _enumerableType = typeof(Enumerable);

    public static IEnumerable CastAsType(this IEnumerable source, Type targetType)
    {
        var castMethod = _enumerableType.GetMethod("Cast").MakeGenericMethod(targetType);

        return (IEnumerable)castMethod.Invoke(null, new object[] { source });
    } 

    public static IList ToListOfType(this IEnumerable source, Type targetType)
    {
        var enumerable = CastAsType(source, targetType);

        var listMethod = _enumerableType.GetMethod("ToList").MakeGenericMethod(targetType);

        return (IList)listMethod.Invoke(null, new object[] { enumerable });
    } 
}

如果您只是用ToList()替换ToListOfType(queryClause.Type)来电,这应该适用于您的代理人。我实现了CastAsTypeToListOfType方法,以便您可以选择不迭代的集合。我将向未来的读者注意,这些仅在您将动态结果传递给委托人的情况下有用 - 在所有其他情况下,Cast<T>操作将是首选。