[在两个答案都说不清楚后编辑]
我的目标:根据传递给函数的内容是“对象”类型的东西(例如数组、哈希表)还是简单的“字符串”类型的东西,执行不同的操作。如果它只是一个字符串,我会简单地将它包含在电子邮件的正文中。如果它是一个数组或哈希表,我需要对其进行一系列处理以将其转换为 HTML 表。
[原始问题文本]
我正在传递一个变量 $body
到函数 Email-Report
可以是简单的字符串或对象(例如哈希表或数组)。
我想检查 $body
是一个对象,根据不同的情况做不同的事情。
我的问题是 $body
几乎可以是任何东西,而不仅仅是字符串或哈希表。所以我不能只检查 $body.GetType().Name -eq String
我试过$body.GetType().Name
返回
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
但是,如果变量是数组
BaseType
变成
System.Array
所以我无法过滤该属性,也如上所述
$body
变量可能并不总是哈希表或数组。
如果是哈希表,
$var.GetType()
返回
System.Object
的 BaseType ,但是我似乎无法引用 BaseType 属性。
($hash.GetType()).BaseType
返回另一个对象本身,该对象本身具有一个空白的 BaseType 属性。
我也试过
$body.IsObject
和
$body.IsObject()
但这些方法似乎不存在。我也试过
$body -eq [System.Object]
我预计会是
$true
,但它返回
$false
.
不知道从哪里开始 - 我想我遗漏了一些明显的东西或有逻辑错误。
请您参考如下方法:
从这个问题中你的目标或动机是什么并不完全清楚,但这里有:
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)
}
如果你想要一个通用的解决方案来测试某个类型是否出现在对象的类型层次结构中,有以下三种通用方法:
PSTypeNames
-is
接线员 PSTypeNames
PowerShell 中的所有对象都有一个名为
PSTypeNames
的特殊属性。它包含底层对象的类型层次结构中所有类型的类型名称 +(可选)PowerShell 定义的类型扩展名称 - 例如,这就是 PowerShell 区分不同 CIM 类实例格式的方式。
由于
PSTypeName
可以由用户直接操作,这本质上是“不安全的”,但在大多数情况下都可以:
function Test-IsType
{
param(
[object]$InputObject,
[string]$TypeName
)
return $InputObject.PSTypeNames -contains $TypeName
}
内置类型运算符
从 PowerShell 3.0 开始,我们有了两个新的类型运算符:
-is
及其否定的对应物
-isnot
.这些实际上检查底层 .NET 对象的运行时类型,因此它们比检查合成
PSTypeNames
更安全。属性(property):
$Object -is [System.Object] # $true for any value assigned to $Object
"" -is [string] # $true
5 -is [int] # $true
-is
也自动测试基本类型和接口(interface)(以下所有语句都是
$true
):
$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
,除非您特别想只测试基类,而不是接口(interface)。