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

时间:2022-11-11 16:13:50

Assume the following type definitions:

假设以下类型定义:

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

How do I find out whether the type Foo implements the generic interface IBar<T> when only the mangled type is available?

当只有损坏的类型可用时,如何确定Foo类型是否实现了通用接口IBar ?

11 个解决方案

#1


318  

By using the answer from TcKs it can also be done with the following LINQ query:

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

bool isBar = foo.GetType().GetInterfaces().Any(x =>
  x.IsGenericType &&
  x.GetGenericTypeDefinition() == typeof(IBar<>));

#2


32  

You have to go up through the inheritance tree and find all the interfaces for each class in the tree, and compare typeof(IBar<>) with the result of calling Type.GetGenericTypeDefinition if the interface is generic. It's all a bit painful, certainly.

您必须通过继承树查找树中每个类的所有接口,并将typeof(IBar<>)与调用类型的结果进行比较。如果接口是通用的,则使用GetGenericTypeDefinition。当然,这一切都有点痛苦。

See this answer and these ones for more info and code.

更多信息和代码请参见这个答案和这些答案。

#3


19  

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  

As a helper method extension

作为辅助方法扩展。

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);
}

Example usage:

使用示例:

var testObject = new Dictionary<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!

#5


4  

You have to check against a constructed type of the generic interface.

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

You will have to do something like this:

你必须做这样的事情:

foo is IBar<String>

because IBar<String> represents that constructed type. The reason you have to do this is because if T is undefined in your check, the compiler doesn't know if you mean IBar<Int32> or IBar<SomethingElse>.

因为IBar 表示构造的类型。之所以要这样做,是因为如果在检查中没有定义T,编译器不知道您是指IBar 还是IBar

#6


4  

I'm using a slightly simpler version of @GenericProgrammers extension method:

我使用的是稍微简单一点的@ genericprogrammer扩展方法:

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));
}

Usage:

用法:

    if (!featureType.Implements<IFeature>())
        throw new InvalidCastException();

#7


3  

First of all public class Foo : IFoo<T> {} does not compile because you need to specify a class instead of T, but assuming you do something like public class Foo : IFoo<SomeClass> {}

首先,所有公共类Foo: IFoo {}都不会编译,因为您需要指定一个类而不是T,但是假设您执行的是公共类Foo: IFoo {}

then if you do

如果你做

Foo f = new Foo();
IBar<SomeClass> b = f as IBar<SomeClass>;

if(b != null)  //derives from IBar<>
    Blabla();

#8


3  

To tackle the type system completely, I think you need to handle recursion, e.g. IList<T> : ICollection<T> : IEnumerable<T>, without which you wouldn't know that IList<int> ultimately implements IEnumerable<>.

要完整地处理类型系统,我认为您需要处理递归,例如IList : ICollection : 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  

In case you wanted an extension method that would support generic base types as well as interfaces, I've expanded sduplooy's answer:

如果您想要一个扩展方法来支持通用基类型和接口,我扩展了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  

Method to check if the type inherits or implements a generic type:

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

   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


0  

There shouldn't be anything wrong the following:

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

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

For extra credit you could catch AmbiguousMatchException if you wanted to provide a specific generic-type-parameter with your IBar query.

如果您想要为IBar查询提供一个特定的泛型类型参数,那么您可以捕获歧义matchexception。

#1


318  

By using the answer from TcKs it can also be done with the following LINQ query:

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

bool isBar = foo.GetType().GetInterfaces().Any(x =>
  x.IsGenericType &&
  x.GetGenericTypeDefinition() == typeof(IBar<>));

#2


32  

You have to go up through the inheritance tree and find all the interfaces for each class in the tree, and compare typeof(IBar<>) with the result of calling Type.GetGenericTypeDefinition if the interface is generic. It's all a bit painful, certainly.

您必须通过继承树查找树中每个类的所有接口,并将typeof(IBar<>)与调用类型的结果进行比较。如果接口是通用的,则使用GetGenericTypeDefinition。当然,这一切都有点痛苦。

See this answer and these ones for more info and code.

更多信息和代码请参见这个答案和这些答案。

#3


19  

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  

As a helper method extension

作为辅助方法扩展。

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);
}

Example usage:

使用示例:

var testObject = new Dictionary<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!

#5


4  

You have to check against a constructed type of the generic interface.

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

You will have to do something like this:

你必须做这样的事情:

foo is IBar<String>

because IBar<String> represents that constructed type. The reason you have to do this is because if T is undefined in your check, the compiler doesn't know if you mean IBar<Int32> or IBar<SomethingElse>.

因为IBar 表示构造的类型。之所以要这样做,是因为如果在检查中没有定义T,编译器不知道您是指IBar 还是IBar

#6


4  

I'm using a slightly simpler version of @GenericProgrammers extension method:

我使用的是稍微简单一点的@ genericprogrammer扩展方法:

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));
}

Usage:

用法:

    if (!featureType.Implements<IFeature>())
        throw new InvalidCastException();

#7


3  

First of all public class Foo : IFoo<T> {} does not compile because you need to specify a class instead of T, but assuming you do something like public class Foo : IFoo<SomeClass> {}

首先,所有公共类Foo: IFoo {}都不会编译,因为您需要指定一个类而不是T,但是假设您执行的是公共类Foo: IFoo {}

then if you do

如果你做

Foo f = new Foo();
IBar<SomeClass> b = f as IBar<SomeClass>;

if(b != null)  //derives from IBar<>
    Blabla();

#8


3  

To tackle the type system completely, I think you need to handle recursion, e.g. IList<T> : ICollection<T> : IEnumerable<T>, without which you wouldn't know that IList<int> ultimately implements IEnumerable<>.

要完整地处理类型系统,我认为您需要处理递归,例如IList : ICollection : 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  

In case you wanted an extension method that would support generic base types as well as interfaces, I've expanded sduplooy's answer:

如果您想要一个扩展方法来支持通用基类型和接口,我扩展了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  

Method to check if the type inherits or implements a generic type:

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

   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


0  

There shouldn't be anything wrong the following:

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

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

For extra credit you could catch AmbiguousMatchException if you wanted to provide a specific generic-type-parameter with your IBar query.

如果您想要为IBar查询提供一个特定的泛型类型参数,那么您可以捕获歧义matchexception。