357 Stimmen

Prüfen, ob eine Klasse von einer generischen Klasse abgeleitet ist

Ich habe eine generische Klasse in meinem Projekt mit abgeleiteten Klassen.

public class GenericClass<T> : GenericInterface<T>
{
}

public class Test : GenericClass<SomeType>
{
}

Gibt es eine Möglichkeit, herauszufinden, ob ein Type Objekt ist abgeleitet von GenericClass ?

t.IsSubclassOf(typeof(GenericClass<>))

funktioniert nicht.

10voto

Hier ist eine kleine Methode, die ich erstellt habe, um zu prüfen, ob ein Objekt von einem bestimmten Typ abgeleitet ist. Funktioniert super für mich!

internal static bool IsDerivativeOf(this Type t, Type typeToCompare)
{
    if (t == null) throw new NullReferenceException();
    if (t.BaseType == null) return false;

    if (t.BaseType == typeToCompare) return true;
    else return t.BaseType.IsDerivativeOf(typeToCompare);
}

9voto

DVK Punkte 2636

Das alles lässt sich mit linq leicht bewerkstelligen. Dies wird alle Typen finden, die eine Unterklasse der generischen Basisklasse GenericBaseType sind.

    IEnumerable<Type> allTypes = Assembly.GetExecutingAssembly().GetTypes();

    IEnumerable<Type> mySubclasses = allTypes.Where(t => t.BaseType != null 
                                                            && t.BaseType.IsGenericType
                                                            && t.BaseType.GetGenericTypeDefinition() == typeof(GenericBaseType<,>));

8voto

kad81 Punkte 10372

Einfache Lösung: Erstellen Sie einfach eine zweite, nicht-generische Schnittstelle und fügen Sie diese der generischen Klasse hinzu:

public interface IGenericClass
{
}

public class GenericClass<T> : GenericInterface<T>, IGenericClass
{
}

Überprüfen Sie dies auf jede beliebige Weise mit is , as , IsAssignableFrom , usw.

if (thing is IGenericClass)
{
    // Do work
{

Offensichtlich nur möglich, wenn Sie die Fähigkeit, die generische Klasse (die der OP zu haben scheint) zu bearbeiten, aber es ist ein bisschen eleganter und lesbarer als mit einer kryptischen Erweiterung Methode.

7voto

codybartfast Punkte 6793

Es mag übertrieben sein, aber ich verwende Erweiterungsmethoden wie die folgende. Sie prüfen sowohl die Schnittstellen als auch die Unterklassen. Sie können auch den Typ zurückgeben, der die angegebene generische Definition hat.

Für das Beispiel in der Frage kann es z.B. sowohl gegen eine generische Schnittstelle als auch gegen eine generische Klasse testen. Der zurückgegebene Typ kann verwendet werden mit GetGenericArguments um festzustellen, dass der generische Argumenttyp "SomeType" ist.

/// <summary>
/// Checks whether this type has the specified definition in its ancestry.
/// </summary>   
public static bool HasGenericDefinition(this Type type, Type definition)
{
    return GetTypeWithGenericDefinition(type, definition) != null;
}

/// <summary>
/// Returns the actual type implementing the specified definition from the
/// ancestry of the type, if available. Else, null.
/// </summary>
public static Type GetTypeWithGenericDefinition(this Type type, Type definition)
{
    if (type == null)
        throw new ArgumentNullException("type");
    if (definition == null)
        throw new ArgumentNullException("definition");
    if (!definition.IsGenericTypeDefinition)
        throw new ArgumentException(
            "The definition needs to be a GenericTypeDefinition", "definition");

    if (definition.IsInterface)
        foreach (var interfaceType in type.GetInterfaces())
            if (interfaceType.IsGenericType
                && interfaceType.GetGenericTypeDefinition() == definition)
                return interfaceType;

    for (Type t = type; t != null; t = t.BaseType)
        if (t.IsGenericType && t.GetGenericTypeDefinition() == definition)
            return t;

    return null;
}

7voto

vexe Punkte 5003

Ergänzend zur Antwort von @jaredpar habe ich die folgenden Informationen, um nach Schnittstellen zu suchen:

public static bool IsImplementerOfRawGeneric(this Type type, Type toCheck)
{
    if (toCheck.GetTypeInfo().IsClass)
    {
        return false;
    }

    return type.GetInterfaces().Any(interfaceType =>
    {
        var current = interfaceType.GetTypeInfo().IsGenericType ?
                    interfaceType.GetGenericTypeDefinition() : interfaceType;
        return current == toCheck;
    });
}

public static bool IsSubTypeOfRawGeneric(this Type type, Type toCheck)
{
    return type.IsInterface ?
          IsImplementerOfRawGeneric(type, toCheck)
        : IsSubclassOfRawGeneric(type, toCheck);
}

Ex:

Console.WriteLine(typeof(IList<>).IsSubTypeOfRawGeneric(typeof(IList<int>))); // true

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X