views:

2311

answers:

6

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?

A: 

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>.

Andrew Hare
+9  A: 

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.

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

Jon Skeet
why not just cast to IBar<SomeClass> and check for null? (I mean casting with 'as' of course)
pablito
T is unknown and cannot be cast to a specific type.
sduplooy
@sduplooy: maybe I am missing something how can T be unknown? it would compile public class Foo : IFoo<T> {}
pablito
+7  A: 
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;
    }
}
TcKs
Since typeof( Foo ) returns the a System.Type object (describing Foo), the GetType() call will always return the type for System.Type. You should change to typeof(Foo).GetInterfaces()
Michael Meadows
if(genericType == typeof(IFoo<>) should be if(genericType == typeof(IBar<>)...
sduplooy
@sduplooy: You are right. It was my mistake.
TcKs
+1  A: 

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> {}

then if you do

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

if(b != null)  //derives from IBar<>
    Blabla();
pablito
+25  A: 

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

bool isBar = foo.GetType().GetInterfaces().Any(x =>
  x.IsGenericType &&
  x.GetGenericTypeDefinition() == typeof(IBar<>));
sduplooy
This is a very elegant solution! The others I've seen on SO use foreach loops or longer LINQ queries. Keep in mind though that to use this, you need to have .NET framework 3.5.
Daniel T.
I recommend you make this an extension method a la http://bit.ly/ccza8B -- will clean this up quite nicely!
Brad Heller
+2  A: 

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!
GenericProgrammer
"IsAssignableFrom" was exactly what I was looking for - thanks
Jesper