【问题标题】:How do I test if the <T> in Enumerable<T> implements an interface, if <T> is dynamic?如果 <T> 是动态的,如何测试 Enumerable<T> 中的 <T> 是否实现接口?
【发布时间】:2014-01-25 23:42:06
【问题描述】:

我有一个接受IEnumerable&lt;dynamic&gt; 的方法

有没有办法测试方法内部的动态类型,看看它是否实现了特定的接口?

我的意图是这样的:

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

更新

我应该包括这个重要的事实:&lt;T&gt; 是动态的。

请原谅,我正在编码的地方已经接近午夜了。 :-$

【问题讨论】:

    标签: c# generics interface ienumerable


    【解决方案1】:

    你可以使用Type.IsAssignableFrom方法:

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

    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 是动态的。
    • 您期望什么结果?你能提供示例输入/输出吗?
    【解决方案2】:

    is 关键字用于 objectreflection 用于 类型

    您可以使用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 是动态的。所以我认为这不适用于我的情况。
    • @MartinHansenLennox 我已经更新了我的帖子,其中包含注释和针对您的动态问题的潜在解决方案。
    • @MartinHansenLennox 更新了第三种解决方案,因为我想了更多。
    • 任何来这里的人也应该看看@wdosanjos的回答
    • @MartinHansenLennox 您可以使用 foreach 循环修改我的第二个示例,以便轻松地使用 IsAssignableFrom。 wdosanjos 的响应不完整,如果列表为空会抛出 null ref 异常。
    【解决方案3】:

    请尝试以下操作。由于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。
    猜你喜欢
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多