user1096188
user1096188

Reputation: 1839

Determining if type is a subclass of a generic type

class Program
{
    static void Main(string[] args) {
        Check(new Foo());
        Check(new Bar());
    }
    static void Check<T>(T obj) {
        // "The type T cannot be used as type parameter..."
        if (typeof(T).IsSubclassOf(typeof(Entity<T>))) {
            System.Console.WriteLine("obj is Entity<T>");
        }
    }
}
class Entity<T> where T : Entity<T>{ }
class Foo : Entity<Foo> { }
class Bar { }

What is the proper way to make this thing compile? I could subclass Entity<T> from a non generic EntityBase class, or could just try to typeof(Entity<>).MakeGenericType(typeof(T)) and see if it succeeds, but is there a way that doesn't abuse try { } catch { } blocks or mauls the type hierarchy?

There are some methods on Type that look like they could be useful, like GetGenericArguments and GetGenericParameterConstraints but I'm totally clueless as to how use them...

Upvotes: 4

Views: 2685

Answers (1)

Maarten
Maarten

Reputation: 22945

Something like this should work.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4 {
    class Program {
        static void Main(string[] args) {
            Check(new Foo());
            Check(new Bar());
            Console.ReadLine();
        }
        static void Check<T>(T obj) {
            // "The type T cannot be used as type parameter..."
            if (IsDerivedOfGenericType(typeof(T), typeof(Entity<>))) {
                System.Console.WriteLine(string.Format("{0} is Entity<T>", typeof(T)));
            }
        }

        static bool IsDerivedOfGenericType(Type type, Type genericType) {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType)
                return true;
            if (type.BaseType != null) {
                return IsDerivedOfGenericType(type.BaseType, genericType);
            }
            return false;
        }
    }
    class Entity<T> where T : Entity<T> { }
    class Foo : Entity<Foo> { }
    class Bar { }
}

Upvotes: 4

Related Questions