Отражение .NET: обнаружение IEnumerable <T> - PullRequest
11 голосов
/ 30 октября 2009

Я пытаюсь определить, является ли конкретный экземпляр объекта Type универсальным "IEnumerable" ...

Лучшее, что я могу придумать:

// theType might be typeof(IEnumerable<string>) for example... or it might not
bool isGenericEnumerable = theType.GetGenericTypeDefinition() == typeof(IEnumerable<object>).GetGenericTypeDefinition()
if(isGenericEnumerable)
{
    Type enumType = theType.GetGenericArguments()[0];
    etc. ...// enumType is now typeof(string) 

Но это кажется немного косвенным - есть ли более прямой / элегантный способ сделать это?

Ответы [ 3 ]

22 голосов
/ 30 октября 2009

Вы можете использовать

if(theType.IsGenericType && theType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
    Type underlyingType = theType.GetGenericArguments()[0];
    //do something here
}

РЕДАКТИРОВАТЬ: добавлена ​​проверка IsGenericType, спасибо за полезные комментарии

4 голосов
/ 30 октября 2009

Вы можете использовать этот фрагмент кода, чтобы определить, реализует ли конкретный тип интерфейс IEnumerable<T>.

Type type = typeof(ICollection<string>);

bool isEnumerable = type.GetInterfaces()       // Get all interfaces.
    .Where(i => i.IsGenericType)               // Filter to only generic.
    .Select(i => i.GetGenericTypeDefinition()) // Get their generic def.
    .Where(i => i == typeof(IEnumerable<>))    // Get those which match.
    .Count() > 0;

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

Вы должны иметь возможность изменить его для проверки аргументов типа, передаваемых каждому интерфейсу.

2 голосов
/ 30 октября 2009

Обратите внимание, что вы не можете вызвать GetGenericTypeDefinition() для неуниверсального типа, поэтому сначала проверьте с помощью IsGenericType.

Я не уверен, хотите ли вы проверить, реализует ли тип универсальный IEnumerable<> или вы хотите увидеть, является ли тип интерфейса IEnumerable<>. В первом случае используйте следующий код (во втором случае внутренняя проверка с interfaceType):

if (typeof(IEnumerable).IsAssignableFrom(type)) {
    foreach (Type interfaceType in type.GetInterfaces()) {
        if (interfaceType.IsGenericType && (interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) {
            Console.WriteLine("{0} implements {1} enumerator", type.FullName, interfaceType.FullName); // is a match
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...