代码之家  ›  专栏  ›  技术社区  ›  sduplooy

如何确定类型是否实现特定的泛型接口类型

  •  196
  • sduplooy  · 技术社区  · 16 年前

    假定以下类型定义:

    public interface IFoo<T> : IBar<T> {}
    public class Foo<T> : IFoo<T> {}
    

    我怎样才能知道 Foo 实现通用接口 IBar<T> 当只有损坏类型可用时?

    11 回复  |  直到 7 年前
        1
  •  344
  •   sduplooy    16 年前

    通过使用来自tcks的答案,还可以通过以下LINQ查询来完成:

    bool isBar = foo.GetType().GetInterfaces().Any(x =>
      x.IsGenericType &&
      x.GetGenericTypeDefinition() == typeof(IBar<>));
    
        2
  •  31
  •   Community CDub    7 年前

    您必须遍历继承树,找到树中每个类的所有接口,然后比较 typeof(IBar<>) 呼叫的结果 Type.GetGenericTypeDefinition 如果 接口是通用的。当然,这有点痛苦。

    this answer these ones 更多信息和代码。

        3
  •  21
  •   TcKs    16 年前
    public interface IFoo<T> : IBar<T> {}
    public class Foo : IFoo<Foo> {}
    
    var implementedInterfaces = typeof( Foo ).GetInterfaces();
    foreach( var interfaceType in implementedInterfaces ) {
        if ( false == interfaceType.IsGeneric ) { continue; }
        var genericType = interfaceType.GetGenericTypeDefinition();
        if ( genericType == typeof( IFoo<> ) ) {
            // do something !
            break;
        }
    }
    
        4
  •  9
  •   Peter Mortensen icecrime    7 年前

    作为辅助方法扩展

    public static bool Implements<I>(this Type type, I @interface) where I : class
    {
        if(((@interface as Type)==null) || !(@interface as Type).IsInterface)
            throw new ArgumentException("Only interfaces can be 'implemented'.");
    
        return (@interface as Type).IsAssignableFrom(type);
    }
    

    示例用法:

    var testObject = new Dictionary<int, object>();
    result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!
    
        5
  •  4
  •   Andrew Hare    16 年前

    您必须检查通用接口的构造类型。

    你必须这样做:

    foo is IBar<String>
    

    因为 IBar<String> 表示构造的类型。你必须这样做的原因是如果 T 在您的检查中没有定义,编译器不知道您的意思是 IBar<Int32> IBar<SomethingElse> .

        6
  •  4
  •   Ben Foster    13 年前

    我正在使用稍微简单一点的@genericProgrammers扩展方法:

    public static bool Implements<TInterface>(this Type type) where TInterface : class {
        var interfaceType = typeof(TInterface);
    
        if (!interfaceType.IsInterface)
            throw new InvalidOperationException("Only interfaces can be implemented.");
    
        return (interfaceType.IsAssignableFrom(type));
    }
    

    用途:

        if (!featureType.Implements<IFeature>())
            throw new InvalidCastException();
    
        7
  •  3
  •   Pablo Retyk    16 年前

    首先 public class Foo : IFoo<T> {} 不编译,因为您需要指定一个类而不是t,但假设您执行类似的操作 public class Foo : IFoo<SomeClass> {}

    如果你这样做

    Foo f = new Foo();
    IBar<SomeClass> b = f as IBar<SomeClass>;
    
    if(b != null)  //derives from IBar<>
        Blabla();
    
        8
  •  3
  •   Sebastian Good    13 年前

    为了完全处理类型系统,我认为您需要处理递归,例如 IList<T> : ICollection<T> : IEnumerable<T> 如果没有它你就不会知道 IList<int> 最终实现 IEnumerable<> .

        /// <summary>Determines whether a type, like IList&lt;int&gt;, implements an open generic interface, like
        /// IEnumerable&lt;&gt;. Note that this only checks against *interfaces*.</summary>
        /// <param name="candidateType">The type to check.</param>
        /// <param name="openGenericInterfaceType">The open generic type which it may impelement</param>
        /// <returns>Whether the candidate type implements the open interface.</returns>
        public static bool ImplementsOpenGenericInterface(this Type candidateType, Type openGenericInterfaceType)
        {
            Contract.Requires(candidateType != null);
            Contract.Requires(openGenericInterfaceType != null);
    
            return
                candidateType.Equals(openGenericInterfaceType) ||
                (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition().Equals(openGenericInterfaceType)) ||
                candidateType.GetInterfaces().Any(i => i.IsGenericType && i.ImplementsOpenGenericInterface(openGenericInterfaceType));
    
        }
    
        9
  •  1
  •   Philip Pittle    9 年前

    如果您想要一个支持通用基类型和接口的扩展方法,我已经扩展了sduplooy的答案:

        public static bool InheritsFrom(this Type t1, Type t2)
        {
            if (null == t1 || null == t2)
                return false;
    
            if (null != t1.BaseType &&
                t1.BaseType.IsGenericType &&
                t1.BaseType.GetGenericTypeDefinition() == t2)
            {
                return true;
            }
    
            if (InheritsFrom(t1.BaseType, t2))
                return true;
    
            return
                (t2.IsAssignableFrom(t1) && t1 != t2)
                ||
                t1.GetInterfaces().Any(x =>
                  x.IsGenericType &&
                  x.GetGenericTypeDefinition() == t2);
        }
    
        10
  •  1
  •   Derek Greer    7 年前

    方法检查类型是否继承或实现泛型类型:

       public static bool IsTheGenericType(this Type candidateType, Type genericType)
        {
            return
                candidateType != null && genericType != null &&
                (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition() == genericType ||
                 candidateType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == genericType) ||
                 candidateType.BaseType != null && candidateType.BaseType.IsTheGenericType(genericType));
        }
    
        11
  •  -1
  •   Peter Mortensen icecrime    7 年前

    以下内容不应该有任何问题:

    bool implementsGeneric = (anObject.Implements("IBar`1") != null);
    

    如果您想为IBAR查询提供一个特定的泛型类型参数,那么对于额外的学分,您可以捕获含糊不清的matchException。