Как получить универсальные типы аргументов универсального типа из производного типа в c # - PullRequest
5 голосов
/ 30 мая 2011

Предположим, у меня есть:

class MyBase<T1, T2>{}

class MyConcreteBase<T2> : MyBase<ConcreteType1, T2>{}

class MyConcrete1 : MyConcreteBase<ConcreteType2>{}

class MyConcrete2 : MyBase<ConcreteType1, ConcreteType2>{}

Как получить типы T1 и T2, если у меня есть экземпляр MyConcrete1 или MyConcrete2 или MyConcreteBase или любой другой экземпляртип, полученный из MyBase<T1, T2>

То, как я делаю это сейчас, я "встаю" по цепочке наследования, используя .GetType().BaseType, тогда как BaseType.Name.StartsWith("MyBase"), а затем использую .GetGenericArguments()

Itработает, но я не удовлетворен этим, особенно .StartsWith("MyBase") часть.

У кого-нибудь есть другие предложения?

Ответы [ 6 ]

3 голосов
/ 30 мая 2011

Вы можете пройти вверх по иерархии наследования и найти GenericType, который построен из BaseType<,>.Попробуйте:

var type = c.GetType();
Type baseType = type;
while(null != (baseType = baseType.BaseType)) 
{
    if (baseType.IsGenericType) 
    {
        var generic = baseType.GetGenericTypeDefinition();
        if (generic == typeof(MyBase<,>)) 
        {
            var genericTypes = baseType.GetGenericArguments();
            // genericTypes has the type argument used to construct baseType.
            break;
        }
    }
}   
2 голосов
/ 30 мая 2011

Да, не используйте разбор строк.Вы можете просто использовать BaseType.IsAssignableFrom(typeof(MyBase<,>)) (возможно, придется поменять местами BaseType и MyBase<,> - я всегда путаюсь с этим).

Также может быть проще представить типы как свойства в вашем базовом классеНапример:

public Type T1_Type { get { return typeof(T1); } }
public Type T2_Type { get { return typeof(T2); } }

Я должен спросить, зачем вам нужно извлекать эти параметры типа?Это кодовый запах для меня.

РЕДАКТИРОВАТЬ: Я должен добавить, что вы не можете использовать IsAssignableFrom, как для дженериков.Посмотрите этот ответ для полного решения: Как определить, является ли тип другим универсальным типом

0 голосов
/ 30 мая 2011

Вот функция, которая будет принимать любой тип (при условии, что у него есть базовый класс с общими параметрами) и возвращать типы общих параметров базового класса этого экземпляра:

public Type[] BaseGenericTypes<T>(T instance)
    {
        Type instanceType = instance.GetType();

        Type objectType = new object().GetType();

        while (instanceType.BaseType != objectType)
        {
            instanceType = instanceType.BaseType;
        }
        return instanceType.GetGenericArguments();
    }

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

0 голосов
/ 30 мая 2011

Я не могу придумать ничего умного, поэтому я, вероятно, просто сделаю это:

class MyBase<T1, T2> {
    protected Type GetT1() { return typeof(T1); }
    protected Type GetT2() { return typeof(T2); }
}
0 голосов
/ 30 мая 2011

Вы имеете в виду: Метод Type.GetGenericArguments ?

0 голосов
/ 30 мая 2011

Хорошо, если вы расскажете нам немного больше о том, чего хотите достичь. Догадываясь, что вы думаете, я бы сказал: просто пройдите полную цепочку наследования, пока BaseType не null. А затем проверьте для каждого типа, является ли он общим, и если да, позвоните GetGenericArguments. Должно быть несколько предикатов и одно или два выражения LINQ.

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