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

Jon Skeet
people
quotationmark

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

people

See more on this question at Stackoverflow