Search code examples
c#inheritancetypesabstracttype-parameter

Get the type parameter of a Class, by knowing only the Type of Class


I have a base abstract class having a type parameter from another abstract class, as:

public abstract class Database<T> where T : DatabaseItem, new() { //... }

public abstract class DatabaseItem { //... }

Then I have number of children classes inherent from it:

public class ShopDatabase : Database<ShopItem> {}
public class ShopItem : DatabaseItem {}

public class WeaponDatabase : Database<WeaponItem> {}
public class WeaponItem : DatabaseItem {}

//...

Now the problem is, I have an array of Type of Database as:

private static readonly Type[] DATABASE_TYPES = new Type[] {
    typeof (ShopDatabase),
    typeof (WeaponDatabase)
};

And I want to get all their type parameters as another array, something like this:

Type[] databaseItemTypes = MyFunction (DATABASE_TYPES);
// databaseItemTypes will be an array as: [ShopDatabaseItem, WeaponDatabaseItem]

It may be similar to this question but I don't even have a instance of the Class, so...


Solution

  • If you're looking for the type arguments for a specific class, that's relatively easy:

    static Type GetDatabaseTypeArgument(Type type)
    {
        for (Type current = type; current != null; current = current.BaseType)
        {
            if (current.IsGenericType && current.GetGenericTypeDefinition() == typeof(Database<>))
            {
                return current.GetGenericTypeArguments()[0];
            }
        }
        throw new ArgumentException("Type incompatible with Database<T>");
    }
    

    Then you can use:

    Type[] databaseItemTypes = DatabaseTypes.Select(GetDatabaseTypeArgument).ToArray();
    

    Note that if you have a class of:

    public class Foo<T> : Database<T>
    

    ... then you'll end up getting a Type reference representing the T in Foo<T>. Getting rid of that for a type with a base type of Foo<string> for example would be tricky. Hopefully you're not in that situation...