Как определить тип объекта в PowerShell


Оглавление

1. Определение типа объекта в PowerShell

2. Определение типа объекта с помощью метода .GetType() (а также .GetType().Name и .GetType().FullName

3. Получение типа объекта с помощью Get-Member

4. Проверка типов объектов с помощью операторов типа -is и -isnot

5. Как проверить тип элементов коллекции

6. Свойство .GetType().IsArray для проверки, является ли объект массивом

Заключение


1. Определение типа объекта в PowerShell

В PowerShell нет специального инструмента (например, командлета или свойства) которое показывало бы тип объекта. Тем не менее, некоторые командлеты показывают тип объекта как часть их вывода, также тип объекта можно узнать с помощью .NET API.

Из-за различных подходов вывод может различаться и немного сбивать с толку.

Также ещё больше запутывает то, что некоторые объекты являются коллекциями, содержащими объекты различных типов — мы остановимся на этом в самом конце, в том числе рассмотрим способы перебора всех элементов коллекции и определение их типа.


Я покажу здесь несколько способов определения типа объекта в PowerShell и, возможно, вы сможете подобрать что-то подходящее под ваши задачи.

Для примеров в этой заметке мы будем определять тип переменных со следующим содержимым:

$a = 'pwsh.ru and Suay.site' # String
$b = 456 # Number, Int
$c = @{ Number = 1; Shape = "Square"; Color = "Blue"} # Hash-table
$d = 22,5,10,8,12,9,80,'Suay.site','pwsh.ru' # Array
$e = Get-ChildItem
$f = Get-Date
$g = Get-ChildItem | Get-Member

2. Определение типа объекта с помощью метода .GetType() (а также .GetType().Name и .GetType().FullName

Вы можете определить тип объекта с помощью его метода GetType():

$a.GetType()
$b.GetType()
$c.GetType()
$d.GetType()
$e.GetType()
$f.GetType()
$g.GetType()

Метод .GetType() предоставляет метаданные об объекте, такие как его имя, базовый тип, сборка, из которой он взят, и т. д.

Как можно увидеть, тип объекта указан в столбце Name. Но для массива указан тип «Object[]», что в целом правильно, но является слишком общей характеристикой. Зато в столбце BaseType можно увидеть упоминание массива.

Вы можете ограничиться выводом только поля Name, для этого используйте .GetType().Name. Например:

$a.GetType().Name
$b.GetType().Name
$c.GetType().Name
$d.GetType().Name
$e.GetType().Name
$f.GetType().Name
$g.GetType().Name

Возможно, в каких-то ситуациях вам больше подойдёт FullName:

$a.GetType().FullName
$b.GetType().FullName
$c.GetType().FullName
$d.GetType().FullName
$e.GetType().FullName
$f.GetType().FullName
$g.GetType().FullName

Как вы можете помнить, для массивов более точное определение типа данных содержится в свойстве BaseType, при желании, вы можете получить только имя BaseType добавив к вашего объекту .GetType().BaseType.Name:

$a.GetType().BaseType.Name
$b.GetType().BaseType.Name
$c.GetType().BaseType.Name
$d.GetType().BaseType.Name
$e.GetType().BaseType.Name
$f.GetType().BaseType.Name
$g.GetType().BaseType.Name

Документация о методе Object.GetType: https://learn.microsoft.com/en-us/dotnet/api/system.object.gettype

3. Получение типа объекта с помощью Get-Member

Get-Member в основном предназначен для получения информации о членах (свойствах и методах) объекта (или статических членах класса, если вы используете параметр -Static). Например:

$a | Get-Member

Обратите внимание на первую строку, которая начинается с «TypeName:». Вы можете получить только вывод TypeName с помощью следующей конструкции:

(OBJECT | Get-Member)[0].TypeName

В этой команде замените OBJECT на объект, чей тип вы хотите узнать.

Примеры:

($a | Get-Member)[0].TypeName
($b | Get-Member)[0].TypeName
($c | Get-Member)[0].TypeName
($d | Get-Member)[0].TypeName
($e | Get-Member)[0].TypeName
($f | Get-Member)[0].TypeName
($g | Get-Member)[0].TypeName

Мы получили более чёткое представление о некоторых объектах (что-то более чем «Object[]»), например:

  • DateTime
  • DirectoryInfo
  • MemberDefinition

Но для массива мы получили тип «Int32», что является явной ошибкой. Имейте ввиду, что если вам нужна информация о членах объекта коллекции, вы должны использовать

Get-Member -InputObject $COLLECTION

вместо передачи объекта по конвейеру

$COLLECTION | Get-Member

потому что использование конвейера развернёт коллекцию, и вы получите членов элементов коллекции, а не членов самого объекта коллекции.

То есть попробуйте следующую конструкцию:

(Get-Member -InputObject OBJECT)[0].TypeName

В этой команде замените OBJECT на объект, чей тип вы хотите узнать.


Примеры:

(Get-Member -InputObject $a)[0].TypeName
(Get-Member -InputObject $b)[0].TypeName
(Get-Member -InputObject $c)[0].TypeName
(Get-Member -InputObject $d)[0].TypeName
(Get-Member -InputObject $e)[0].TypeName
(Get-Member -InputObject $f)[0].TypeName
(Get-Member -InputObject $g)[0].TypeName


Как можно увидеть, остался тип данных DateTime, а DirectoryInfo и MemberDefinition вновь обозначены как Object[]. Массивы тоже обозначены как Object[].

4. Проверка типов объектов с помощью операторов типа -is и -isnot

-is и -isnot относятся к операторам типа и к операторам сравнения.

Оператор -is возвращает TRUE, если входные данные являются экземпляром указанного типа .NET.

Оператор -isnot возвращает TRUE, если входные данные не являются экземпляром указанного типа .NET.

Примеры:

$a -is [String]
True

$d -is [Array]
True

$e -is [System.IO.DirectoryInfo]
False

$e[0] -is [System.IO.DirectoryInfo]
True

(get-date) -is [DateTime]
True

(get-date) -isnot [DateTime]
False

Больше примеров смотрите по ссылкам:

5. Как проверить тип элементов коллекции

Надеюсь, вы не слишком запутались к этому моменту. Если нет, то мы продолжаем 🙂

Некоторые из объектов, тип которых мы хотим проверить, являются коллекциями. В приведённых выше командах они зачастую определялись как «Object[]» или массив. Но эти объекты могут содержать в себе элементы коллекции разных типов.

Чтобы перечислить элементы коллекции и проверить их типы, вы можете использовать следующую конструкцию:

OBJECT | ForEach-Object {$_.GetType().Name}

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

Например:

$a | ForEach-Object {$_.GetType().Name}


В переменной $a находится только один элемент и это строка.

В переменной $d содержится массив, проверим его содержимое:

$d | ForEach-Object {$_.GetType().Name}

Пример вывода:

Int32
Int32
Int32
Int32
Int32
Int32
Int32
String
String

То есть мы можем увидеть, что некоторые члены массива являются числами, а некоторые строками.

В переменной $e содержится результат выполнения комнадлета Get-ChildItem:

$e | ForEach-Object {$_.GetType().Name}

В этой коллекции два типа объектов:

  • DirectoryInfo
  • FileInfo

Рассмотренные чуть выше операторы типа (-is и -isnot) всегда работают с входным объектом целиком. То есть, если входной объект является коллекцией, тестируется тип коллекции, а не типы элементов коллекции. Именно поэтому различается вывод для $e (проверяется тип всей коллекции):

$e -is [System.IO.DirectoryInfo]

И для $e[0] (проверяется тип первого элемента коллекции):

$e[0] -is [System.IO.DirectoryInfo]

Но при желании вы также можете делать проверку с помощью -is и -isnot каждого элемента коллекции, например:

$e | ForEach-Object {$_ -is [System.IO.DirectoryInfo]}

6. Свойство .GetType().IsArray для проверки, является ли объект массивом

У метода .GetType() имеется свойство .IsArray, которое позволяет проверить, является ли объект массивом:

OBJECT.GetType().IsArray

В этой команде замените OBJECT на объект, который вы проверяете.

Примеры:

$a.GetType().IsArray
False

$b.GetType().IsArray
False

$c.GetType().IsArray
False

$d.GetType().IsArray
True

$e.GetType().IsArray
True

$f.GetType().IsArray
False

$g.GetType().IsArray
True

Конечно же, имеется и много других способов проверить, является ли объект массивом или другим типом (строкой, числом, хеш-таблицей и так далее), свойство .GetType().IsArray здесь упоминается по той причине, что в этой заметке мы довольно много говорили о методе .GetType(). Если вас интересует, имеются ли свойства вроде .GetType().IsString, .GetType().IsInt и другие подобные, то ответ отрицательный — таких свойств нет.

Заключение

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

Хеш-таблицы расцениваются как один объект и хранимые значения не перебираются с помощью ForEach-Object.

А массив расценивается как коллекция, элементы который можно перебрать с ForEach-Object.

Вывод командлета может быть как массивом, так и особым объектом — например, выводом Get-Date является один объект [DateTime].

Выводом командлета может быть также массив, состоящий из объектов. Например, вывод Get-ChildItem представляет собой массив объектов [System.IO.DirectoryInfo] и [System.IO.FileSystemInfo].


Рекомендуется Вам:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *