如果 <T> 是动态类型,我该如何测试 Enumerable<T> 中的 <T> 是否实现了一个接口?

3

我有一个接受 IEnumerable<dynamic> 的方法。

在方法内部,是否有一种方法可以测试动态类型,以查看它是否实现了特定的接口?

我的意图是像这样:

public void myMethod(IEnumerable<dynamicT> enumerable)
{
    if (dynamicT is IInterface)
    {
        // do one thing
    }
    else if (dynamicT is IAnotherInterface)
    {
        // do another thing
    }
}

更新

我应该包含这个重要的事实:<T>是动态的。

请原谅,我现在编程的时候已经接近午夜了。 :-$

3个回答

5

您可以使用Type.IsAssignableFrom方法:

确定当前Type的实例是否可以从指定Type的实例分配。

public void myMethod(IEnumerable<T> enumerable)
{
    if (typeof(IInterface).IsAssignableFrom(typeof(T))
    {
        // do one thing
    }
    else if (typeof(IAnotherInterface).IsAssignableFrom(typeof(T))
    {
        // do another thing
    }
}

非常感谢您的回答,完美地解决了我提出的问题。不幸的是,我遗漏了一个非常重要的信息,即T是动态的。 - Martin Hansen Lennox
你期望什么结果?能提供样例输入/输出吗? - MarcinJuraszek

3
is 关键字用于检查对象类型,而需要使用 reflection 来获取类型:
您可以使用 typeof(T).GetInterfaces() 来获取特定类型应用的所有接口。
public void MyMethod(IEnumerable<T> enumerable)
{
    var typeInterfaces = typeof(T).GetInterfaces();

    if (typeInterfaces.Contains(typeof(IInterface))) {
        // Something
    }
    else if(typeInterfaces.Contains(typeof(IAnotherInterface))) {
        // Something Else
    }
}

============ 根据评论更新 ============

如果 T 是动态的,你无法从类型本身获得所需的信息,因为 T 可以同时代表许多不同的类型

然而,你可以循环每个元素并使用is关键字测试对象本身。

public static void MyMethod<T>(IEnumerable<T> enumerable)
{
    foreach (var dynObj in enumerable)
    {
        var typeInterfaces = dynObj.GetType().GetInterfaces();

        if (typeInterfaces.Contains(typeof(IInterface))) {
            // Something
        }
        else if(typeInterfaces.Contains(typeof(IAnotherInterface))) {
            // Something Else
        }
    }
}

或者,如果您只想测试可枚举对象中的所有可能接口,则可以执行此操作:

public static void MyMethod<T>(IEnumerable<T> enumerable)
{
    var allInterfaces = enumerable.SelectMany(e => e.GetType().GetInterfaces()).ToList();

    if (allInterfaces.Contains(typeof(ITheFirstInterface)))
    {
        Console.WriteLine("Has The First Interface");
    }

    if (allInterfaces.Contains(typeof(ITheSecondInterface)))
    {
        Console.WriteLine("Has The Second Interface");
    }
}

Jay,感谢您的回答,它本来可以解决最初的问题。不幸的是,我遗漏了一个非常重要的信息,即T是动态的。所以我认为这对我的情况不起作用。 - Martin Hansen Lennox
@MartinHansenLennox 我已经更新了我的帖子,并提供了关于你的动态问题的注释和潜在解决方案。 - Timeout
@MartinHansenLennox 更新了第三个解决方案,因为我再想了一下。 - Timeout
每个人来这里都应该查看@wdosanjos的回答。 - Martin Hansen Lennox
@MartinHansenLennox 您可以轻松地使用foreach循环重构我的第二个示例,以使用IsAssignableFrom。wdosanjos的回答不完整,如果列表为空,它将抛出空引用异常。 - Timeout

1
请尝试以下操作。由于T是动态的,您需要查看列表中的第一个项目以找出其类型。
public void myMethod<T>(IEnumerable<T> enumerable)
{
    dynamic peek = enumerable.FirstOrDefault();
    Type dtype = peek.GetType();

    if (typeof(IInterface).IsAssignableFrom(dtype))
    {
        // do one thing
    }
    else if (typeof(IAnotherInterface).IsAssignableFrom(dtype))
    {
        // do another thing
    }
}

非常感谢您的回答,我最终采用了jay在上面提供的答案,但我很喜欢使用IsAssignableFrom。 - Martin Hansen Lennox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接