Как проверить, не является ли объект, который я получаю как результат метода , ValueType и не IEnumerable<ValueType>?

Вот что я написал:

MethodInfo selectedOverload = SelectOverload(selectedMethodOverloads);
object result = ExecuteAndShowResult(selectedOverload);
ExploreResult(result);

private static void ExploreResult(object result)
{
 if (result != null &&
     !(result is ValueType) &&
     !((IEnumerable)result).GetType().GetProperty("Item").PropertyType) is ValueType)
    )
    Console.WriteLine("explore");
}

К сожалению, тип PropertyType - Type, его содержимое - это тип, который мне нужно проверить (например, int), но я не знаю, как это сделать.

РЕДАКТИРОВАТЬ:

Хорошо, .IsValueType работал, но теперь я хочу также исключить строки (которые не распознаются как ValueTypes), и что?

!(((IEnumerable)result).GetType().GetProperty("Item").PropertyType is string)

Не работает!

ИЗМЕНИТЬ 2:

Просто ответил себе:

!(((IEnumerable)result).GetType().GetProperty("Item").PropertyType == typeof(string))

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

!(((IEnumerable)result).GetType().GetProperty("Item").PropertyType == typeof(BaseClass))

Не работает, потому что typeof проверяет тип среды выполнения, и если PropertyType == InheritedClassType он вернет false ...

2
Teejay 2 Окт 2013 в 18:33
2
Вы просто имеете в виду GetProperty("Item").PropertyType.IsValueType?
 – 
Marc Gravell
2 Окт 2013 в 18:35
Спасибо за отзывы! Это именно то, что мне нужно.
 – 
Teejay
2 Окт 2013 в 18:42
Но просто абстрагируюсь от ОП. Что, если мне нужно проверить, имеет ли IEnumerable какой-то тип (даже базовые классы)?
 – 
Teejay
2 Окт 2013 в 18:43
Поскольку параметр имеет тип object, любые типы значений будут помещены в рамку, поэтому вы знаете , что это не тип значения. Вы на 100% уверены, что это всегда ссылочный тип. Если метод универсальный, то он может быть любым.
 – 
Servy
2 Окт 2013 в 19:01
1
Ах, тогда, если это ваша проблема, то ответ таков: является ли что-то типом значения, не является мерой того, можно ли это «разбить». Определенная пользователем структура может иметь поля / свойства / методы, которые, возможно, потребуется дополнительно разбить, в то время как определенный пользователем класс может так же легко не иметь ничего из этого.
 – 
Servy
2 Окт 2013 в 19:26

1 ответ

Лучший ответ

Используйте Type.IsValueType:

private static void ExploreResult(object result)
{
 if (result != null &&
     !(result.GetType().IsValueType) &&
     !((IEnumerable)result).GetType().GetProperty("Item").PropertyType.IsValueType)
    )
    Console.WriteLine("explore");
}

Хотя, если result не является типом значения, но не IEnumerable, вы получите ошибку приведения. Эта проверка требует доработки.

Ответ на вторую часть

!((IEnumerable)result).GetType().GetProperty("Item").PropertyType is string)

Всегда ложно, потому что PropertyType возвращает Type, который никогда не является строкой. Я думаю ты хочешь

!(result.GetType().GetProperty("Item").PropertyType == typeof(string))

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

Ответ на третье изменение

Я хочу проверить наследование от базового класса

Для этого вам нужно type.IsAssignableFrom():

Type itemType = result.GetType().GetProperty("Item").PropertyType;
bool isInheritedFromBaseClass = 
    typeof(BaseClass).IsAssignableFrom(itemType);
4
D Stanley 2 Окт 2013 в 19:05
Ах да, извините, в коде, который я написал здесь, я забыл часть if (result is IEnumerable) :)
 – 
Teejay
2 Окт 2013 в 18:38
Требуется больше работы, чем это - IEnumerable.Item определяется как object. Если вы хотите знать, является ли это типом IEnumerable<T> и что T является типом значения, вам необходимо выполнить некоторую рефлексию относительно параметра универсального типа.
 – 
D Stanley
2 Окт 2013 в 18:41
Нет, «Item» просто возвращает тип перечислителя, только что попробовал.
 – 
Teejay
2 Окт 2013 в 18:46
1
Я ошибался - IEnumerable вообще не имеет свойства Item. Вам повезло, что базовым типом является как IEnumerable, так и IEnumerable<T>, у которого есть строго типизированное свойство Item. Если бы тип был простым IEnumerable (например, ArrayList), вы бы получили исключение времени выполнения.
 – 
D Stanley
2 Окт 2013 в 18:50