Как получить универсальный тип, используемый в универсальном IEnumerable в .net? - PullRequest
3 голосов
/ 13 октября 2010

У нас есть DAL, который мы используем с NHibernate.Search, поэтому классы, которые должны быть проиндексированы, имеют атрибут Indexed(Index:="ClassName"), а каждое свойство, которое необходимо проиндексировать, имеет атрибут Field(Index:=Index.Tokenized, Store:=Store.No). Когда кто-то хочет, чтобы индекс детализировал специальные объекты, есть атрибут IndexedEmbedded()

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

Проблема в том, что среди классов, в которые вы можете углубиться, некоторые из них сами содержатся в универсальных коллекциях IEnumerable. Я хотел бы получить тип, используемый для коллекции (обычно ISet), чтобы проанализировать его тоже.

Так как же получить внутренний тип коллекции?

Private m_TheMysteriousList As ISet(Of ThisClass)
<IndexedEmbedded()> _
Public Overridable Property GetToIt() As ISet(Of ThisClass)
   Get
        Return m_TheMysteriousList
   End Get
   Set(ByVal value As ISet(Of ThisClass))
        m_TheMysteriousList = value
   End Set
End Property

Как мне добраться до ThisClass, когда у меня есть PropertyInfo для GetToIt?

1 Ответ

4 голосов
/ 13 октября 2010

Что-то вроде:

public static Type GetEnumerableType(Type type)
{
    if (type == null) throw new ArgumentNullException();
    foreach (Type interfaceType in type.GetInterfaces())
    {
        if (interfaceType.IsGenericType &&
            interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        {
            return interfaceType.GetGenericArguments()[0];
        }
    }
    return null;
}
...
PropertyInfo prop = ...
Type enumerableType = GetEnumerableType(prop.PropertyType);

(я использовал IEnumerable<T> здесь, но его легко настроить под любой другой подобный интерфейс)

...