如何确定对象的类型是否实现IEnumerable <x>,其中X使用Reflection从Base派生</x>

时间:2010-03-30 18:02:04

标签: c# linq reflection

给一个基类Base,我想写一个方法Test,就像这样:

private static bool Test(IEnumerable enumerable)
{
...
}

如果o的类型实现IEnumerable<X> X从[{1}}派生的Base的任何接口,则Test返回true,这样如果我这样做:

public static IEnumerable<string> Convert(IEnumerable enumerable)
{
    if (Test(enumerable))
    {
        return enumerable.Cast<Base>().Select(b => b.SomePropertyThatIsString);
    }

    return enumerable.Cast<object>().Select(o => o.ToString());
}

......使用Reflection会做正确的事情。我确信这是跨越所有类型接口的问题,以找到符合要求的第一个接口,但我很难找到其中的通用IEnumerable<>

当然,我可以考虑一下:

public static IEnumerable<string> Convert(IEnumerable enumerable)
{
    return enumerable.Cast<object>().Select(o => o is Base ? ((Base)o).SomePropertyThatIsString : o.ToString());
}

......但是把它想象成一个思想实验。

3 个答案:

答案 0 :(得分:16)

您还可以使用看起来像这样的LINQ查询。

public static bool ImplementsBaseType(IEnumerable objects)
{
    int found = ( from i in objects.GetType().GetInterfaces()
                 where i.IsGenericType && 
                       i.GetGenericTypeDefinition() == typeof(IEnumerable<>) &&
                       typeof(MyBaseClass).IsAssignableFrom(i.GetGenericArguments()[0])
                 select i ).Count();

    return (found > 0);
}

此代码假定以下使用语句:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

因为这只是一个思想实验。这是另一种实现作为扩展方法。

public static class ConversionAssistants
{
    public static bool GenericImplementsType(this IEnumerable objects, Type baseType)
    {
        foreach (Type type in objects.GetType().GetInterfaces())
        {
            if (type.IsGenericType)
            {
                if (type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                {
                    if (baseType.IsAssignableFrom(type.GetGenericArguments()[0]))
                        return true;
                }
            }
        }
        return false;
    }
}

答案 1 :(得分:0)

您可以使用Type.FindInterfaces过滤掉该类型实现的所有IEnumerable<>接口,并检查每个接口上的通用参数(通过Type.GetGenericArguments),看看它是否{{1或者继承自Base

更新:以下是一些示例代码:

Base

答案 2 :(得分:-2)

我最近编写了一些需要迭代任何集合的代码。

作为一款传统的.NET应用程序,我甚至没有可用的泛型!

这是一个摘录:

var t = objects.GetType(); // to be compatible with the question

bool isIEnumerable = false;
foreach (var i in t.GetInterfaces())
{
    if (i == typeof(IEnumerable))
    {
        isIEnumerable = true;
        break;
    }
}

我发现即使是.NET 1.1集合类,例如SqlParameterCollection也是IEnumerable 它还捕获了诸如List&lt;&gt;之类的通用集合。因为那些也是IEnumerable。

希望这有助于某人。