IsAssignableFrom на GenericType - PullRequest
       0

IsAssignableFrom на GenericType

3 голосов
/ 03 марта 2012

Не уверен, смогу ли я это сделать или нет, но я пытаюсь понять, наследует ли тип другой тип с общим ограничением.

Вот класс, который я хочу найти:

public class WorkoutCommentStreamMap : ClassMapping<WorkoutCommentStream>...

А вот и тест

var inheritableType = typeof(NHibernate.Mapping.ByCode.Conformist.ClassMapping<>);
var isMappedObject = inheritableType.IsAssignableFrom(typeof(WorkoutCommentStreamMap));

Если я изменю первую строку на ниже, это работает. Но это противоречит цели моего примера. Мой запасной вариант заключается в том, чтобы на всех объектах, которые я хочу найти, использовать нестандартный интерфейс и использовать один и тот же вызов.

var inheritableType = typeof(NHibernate.Mapping.ByCode.Conformist.ClassMapping<WorkoutCommentStream>);

Ответы [ 5 ]

7 голосов
/ 03 марта 2012

Не существует отношения наследования между определением универсального типа и закрытым универсальным типом.Поэтому IsAssignableFrom не будет работать.

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

public static bool IsGenericTypeOf(this Type t, Type genericDefinition)
{
    Type[] parameters = null;
    return IsGenericTypeOf(t, genericDefinition, out parameters);
}

public static bool IsGenericTypeOf(this Type t, Type genericDefinition, out Type[] genericParameters)
{
    genericParameters = new Type[] { };
    if (!genericDefinition.IsGenericType)
    {
        return false;
    }

    var isMatch = t.IsGenericType && t.GetGenericTypeDefinition() == genericDefinition.GetGenericTypeDefinition();
    if (!isMatch && t.BaseType != null)
    {
        isMatch = IsGenericTypeOf(t.BaseType, genericDefinition, out genericParameters);
    }
    if (!isMatch && genericDefinition.IsInterface && t.GetInterfaces().Any())
    {
        foreach (var i in t.GetInterfaces())
        {
            if (i.IsGenericTypeOf(genericDefinition, out genericParameters))
            {
                isMatch = true;
                break;
            }
        }
    }

    if (isMatch && !genericParameters.Any())
    {
        genericParameters = t.GetGenericArguments();
    }
    return isMatch;
}

При использовании образца:

Nullable<int> value = 9;
Assert.IsTrue(value.GetType().IsGenericTypeOf(typeof(Nullable<>)));
5 голосов
/ 03 марта 2012

Вы можете использовать BaseType, IsGenericType и GetGenericTypeDefinition, чтобы восстановить иерархию и попытаться найти ее:

public bool IsClassMapping(Type t)
{
    while (t != null)
    {
        if (t.IsGenericType &&
            t.GetGenericTypeDefinition() == typeof(ClassMapping<>))
        {
            return true;
        }
        t = t.BaseType;
    }
    return false;
}
3 голосов
/ 03 марта 2012

То, что вы пытаетесь сделать, не будет работать, и это явно указано в документации MSDN почему:

Определение универсального типа не может быть назначено из закрытого построенного тип. То есть вы не можете назначить закрытый составной тип MyGenericList<int> к переменной типа MyGenericList<T>

IsAssignableFrom кажется здесь излишним; Вы можете просто использовать BaseType для проверки соответствия типа?

1 голос
/ 03 марта 2012

Никогда не существует отношения наследования между MyType<>, MyType<T> и MyType<ConcreteType>! Следовательно, они никогда не будут совместимы с присвоением.

Исключением являются типы интерфейсов, имеющие общие параметры с ключевым словом in или out.

0 голосов
/ 03 марта 2012

Возможно, это поможет?

    public static bool IsConcreteGenericOf(this Type type, Type openGeneric)
    {
        if (!type.IsGenericType)
            return false;
        if (!openGeneric.IsGenericType)
            return false;
        if (!openGeneric.IsGenericTypeDefinition)
            return false;

        return type.GetGenericTypeDefinition() == openGeneric;
    }

Сорта симлар на ответ Джона Скита, он меня опередил.

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