检查Type或实例是否实现IEnumerable而不管Type T

时间:2015-02-24 17:04:14

标签: c# .net inheritance reflection types

我在当前的项目中做了很多反思,我正在努力提供一些帮助方法,以保持一切都很整洁。

我想提供一对方法来确定类型或实例是否实现IEnumerable - 无论类型T如何。这就是我现在所拥有的:

public static bool IsEnumerable(this Type type)
{
    return (type is IEnumerable);
}

public static bool IsEnumerable(this object obj)
{
    return (obj as IEnumerable != null);
}

当我使用

测试它们时
Debug.WriteLine("Type IEnumerable:   " + typeof(IEnumerable).IsEnumerable());
Debug.WriteLine("Type IEnumerable<>: " + typeof(IEnumerable<string>).IsEnumerable());
Debug.WriteLine("Type List:          " + typeof(List<string>).IsEnumerable());
Debug.WriteLine("Type string:        " + typeof(string).IsEnumerable());
Debug.WriteLine("Type DateTime:      " + typeof(DateTime).IsEnumerable());
Debug.WriteLine("Instance List:      " + new List<string>().IsEnumerable());
Debug.WriteLine("Instance string:    " + "".IsEnumerable());
Debug.WriteLine("Instance DateTime:  " + new DateTime().IsEnumerable());

我得到了这个结果:

Type IEnumerable:   False
Type IEnumerable<>: False
Type List:          False
Type string:        False
Type DateTime:      False
Instance List:      True
Instance string:    True
Instance DateTime:  False

类型方法似乎根本不起作用 - 我原本期望至少为true匹配System.Collections.IEnumerable

我知道string在技术上是可以枚举的,尽管有一些警告。但是,理想情况下,在这种情况下,我需要帮助方法为它返回false。我只需要定义了IEnumerable<T>类型的实例来返回true

我可能只是错过了一些相当明显的东西 - 有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:40)

以下一行

return (type is IEnumerable);

询问“Typetype的实例是否为IEnumerable”,显然不是。

你想做的是:

return typeof(IEnumerable).IsAssignableFrom(type);

答案 1 :(得分:7)

Type.IsAssignableFrom(Type)外,您还可以使用Type.GetInterfaces()

public static bool ImplementsInterface(this Type type, Type interface)
{
    bool implemented = type.GetInterfaces().Contains(interface);
    return implemented;
}

这样,如果您想检查多个接口,可以轻松修改ImplementsInterface以获取多个接口。

答案 2 :(得分:1)

要检查某种类型是否实现IEnumerable ,无论T是否是,都需要检查GenericTypeDefinition。

<!--  https://stackoverflow.com/a/28571411/3195477  -->
<!--  https://stackoverflow.com/a/7487670/3195477  -->
<Style
    x:Key="RadioButtonListBoxStyle"
    TargetType="{x:Type ListBox}"
    >
    <Setter
        Property="BorderBrush"
        Value="Transparent"
        />
    <Setter
        Property="Background"
        Value="Transparent"
        />
    <Setter
        Property="KeyboardNavigation.DirectionalNavigation"
        Value="Cycle"
        />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter
                    Property="Margin"
                    Value="2,2,2,0"
                    />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}"
                                    ContentTemplate="{TemplateBinding ContentPresenter.ContentTemplate}"
                                    ContentTemplateSelector="{TemplateBinding ContentPresenter.ContentTemplateSelector}"
                                    IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                                    />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>