Из вопроса о том, какова ваша цель или мотивация, не совсем понятно, но здесь говорится:
Каждый отдельный объект в PowerShell в конечном итоге наследуется от System.Object
из-за характераСистема типов .NET, так что пытаться использовать сравнение идентификаторов типов - это немного глупо, поскольку вы можете просто сделать:
function Test-IsObject
{
param(
[AllowNull()]
$InputObject
)
return $null -ne $InputObject
}
Если вы хотите проверить, что объект ввопрос не тип значения (т.е. не структура или целочисленный тип, а класс), проверьте свойство IsValueType
типа:
function Test-IsRefType
{
param(
[AllowNull()]
$InputObject
)
return ($null -ne $InputObject -and -not $InputObject.GetType().IsValueType)
}
Если вы хотите, чтобы обобщенное решение проверяло наличие определенного типа в иерархии типов объекта, существует три основных подхода:
- Положитесь на
PSTypeName
- Используйте
-is
operator - Разрешить все базовые типы самостоятельно
PSTypeName
Все объекты в PowerShell имеют специальное свойство PSTypeName
, которое содержит неквалифицированный типимена всех типов в тиерархия типов для базового объекта + (необязательно) определяемые PowerShell имена расширений типов - так PowerShell различает форматирование экземпляров различных классов CIM, например.
Поскольку PSTypeName
может управляться пользователем напрямую, это по сути "небезопасно", но в большинстве случаев будет работать:
function Test-IsType
{
param(
[object]$InputObject,
[string]$TypeName
)
return $InputObject -contains $TypeName
}
Операторы типа встроенных операторов
Начиная с PowerShell 3.0 у нас есть два новых оператора типа: -is
и его отрицательный аналог -isnot
.Они фактически проверяют тип времени выполнения базового объекта .NET, поэтому они более безопасны, чем проверка синтетического свойства PSTypeName
:
$Object -is [System.Object]
"" -is [string]
5 -is [int]
-is
также автоматически проверяет базовые типы и интерфейсы:
$strings = 'a', 'b', 'c' -as [string[]]
$strings -is [array]
$strings -is [System.Collections.Generic.IEnumerable[string]]
$strings -is [object]
Эти операторы вместе со связанным оператором -as
описаны в разделе справки about_Type_Operators .
Разрешите иерархию типов вручную
Наконец, если мы хотим немного подробнее изучить, мы можем разрешить иерархию типов вручную, просто разыменовав GetType().BaseType
, пока не нажмем System.Object
.Ниже приведена простая вспомогательная функция, которая генерирует все базовые типы, с которыми мы затем можем сравнить:
function Get-BaseType
{
param(
[type]$Type,
[switch]$IncludeLeaf
)
if($IncludeLeaf){
# We're "walking backwards", so we'll start by emitting the type itself
$Type
}
# Now go through the BaseType references
# At some point we'll reach System.Object and (BaseType -eq $null)
while($BaseType = $Type.BaseType){
($Type = $BaseType)
}
}
function Test-IsType
{
param(
[object]$InputObject,
[type]$TypeName
)
return $TypeName -in (Get-BaseType -Type $InputObject.GetType() -IncludeLeaf)
}
Обратите внимание, что вы можете просто использовать -is
вместо Test-IsType
, за исключением случаев, когда вы специально хотелитестировать только для базовых классов, но не для интерфейсов.