Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 299
user1096188 Avatar asked Oct 03 '22 20:10

user1096188


1 Answers

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 { }
}
like image 69
Maarten Avatar answered Oct 07 '22 04:10

Maarten