Как проверить, имеют ли два обобщения отношения базовый-подкласс, не создавая их экземпляры? - PullRequest
5 голосов
/ 09 апреля 2011

У меня есть следующие общие классы:

class Base<T> where T : ... { ... }
class Derived<T> : Base<T> where T : ... { ... }
class Another<T> where T : ... { ... }
class DerivedFromDerived<T> : Derived<T> where T : ... { ... }

Где-то в моем коде я хотел бы проверить, наследует ли данный универсальный тип от Base<T>, не создавая конкретный экземпляр универсального. Как мне это сделать?

static bool DerivedFromBase(Type type) { /* ??? */ }

static void Main(string[] args)
{
    Console.WriteLine(DerivedFromBase(typeof(Derived<>)));            // true
    Console.WriteLine(DerivedFromBase(typeof(Another<>)));            // false
    Console.WriteLine(DerivedFromBase(typeof(DerivedFromDerived<>))); // true
    Console.ReadKey(true);
}

РЕДАКТИРОВАТЬ: Спасибо Марк. Теперь я вижу свет. Первоначально я попробовал следующее:

typeof(Derived<>).BaseType == typeof(Base<>)

Видимо, это правильно. Но это не так. Проблема в том, что T Base - это не то же самое, что T Derived. Итак, в

typeof(Base<>)

Base s T - свободный тип. Но в

typeof(Derived<>).BaseType

Base s T связан с Derived 'T, что, в свою очередь, является свободным типом. (Это так здорово, что я LOVE хотел бы увидеть исходный код System.Reflection!) Теперь

typeof(Derived<>).BaseType.GetGenericTypeDefinition()

неограниченно Base х T. Вывод:

typeof(Derived<>).BaseType.GetGenericTypeDefinition() == typeof(Base<>)

А теперь, если вы все извините, моя голова горит.

Ответы [ 2 ]

6 голосов
/ 09 апреля 2011

Не уверен, что это то, что вы ищете, но я думаю, что "IsAssignableFrom" поможет вам.

class Program
{
    class Base<T> { }
    class Derived<T> : Base<T> { }
    class Another<T> { }
    class DerivedFromDerived<T> : Derived<T> { }

    static bool DerivedFromBase<T>(Type type)
    {
        return typeof(Base<T>).IsAssignableFrom(type);
    }

    static void Main(string[] args)
    {
        Console.WriteLine(DerivedFromBase<int>(typeof(Derived<int>)));            // true    
        Console.WriteLine(DerivedFromBase<int>(typeof(Another<int>)));            // false    
        Console.WriteLine(DerivedFromBase<int>(typeof(DerivedFromDerived<int>))); // true   
        Console.ReadKey(true);
    }
}

Для работы с открытой базой введите:

static bool DerivedFromBase(Type type)
    {
        Type openBase = typeof(Base<>);

        var baseType = type;

        while (baseType != typeof(Object) && baseType != null)
        {
            if (baseType.GetGenericTypeDefinition() == openBase) return true;

            baseType = baseType.BaseType;
        }
        return false;
    }
0 голосов
/ 09 апреля 2011

Я придумала эту версию, хотя она кажется немного хакерской.

private static bool IsDerivedFrom(Type derivedType, Type baseType)
{
    if (derivedType.BaseType == null)
        return false;

    if (derivedType.BaseType.GUID == baseType.GUID)
        return true;

    return IsDerivedFrom(derivedType.BaseType, baseType);
}

Она опирается на все типы, имеющие разные GUID, что должно быть правдой, но очевидно, что в следующий четверг произойдет столкновение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...