Powershell - 无法将“System.Management.Automation.PSCustomObject”类型的值转换为“System.Management.Automation.PSCustomObject”类型

Ale*_*xei 2 powershell type-conversion cmdlet powershell-4.0

我正在 Windows 7 下使用 Powershell 4,我的 cmdlet 定义如下:

 Function Transfer-File {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [System.Management.Automation.PSCustomObject]
        $source,

        # other parameters removed for brevity
    )

    # actual logic does not matter 

  }
Run Code Online (Sandbox Code Playgroud)

我这样称呼它:

$hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
Run Code Online (Sandbox Code Playgroud)

$source 是通过解析 JSON 文件获得的,如下所示:

@{Path=some path string here; Pack=False}
Run Code Online (Sandbox Code Playgroud)

Write-Host $source.GetType() 输出:

System.Management.Automation.PSCustomObject
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

无法将“System.Management.Automation.PSCustomObject”类型的“@{Path=some path string here; Pack=False}”值转换为“System.Management.Automation.PSCustomObject”类型。

在绝望地尝试凭经验解决它时,我替换System.Management.Automation.PSCustomObjectpsobject它,它似乎工作正常。

问题:为什么我的System.Management.Automation.PSCustomObject似乎不适合System.Management.Automation.PSCustomObjectcmdlet 原型?


创建对象的完整代码:

### Configuration ###
$cfg = New-Object –TypeName PSObject
$cfg | Add-Member -MemberType NoteProperty –Name Sources –Value @()

# get configuration from json file
$jsonContent = Get-Content .\config.json |  Out-String
$jsonObj = ConvertFrom-Json $jsonContent
$cfg.Sources = $jsonObj.Sources

Foreach ($source in $cfg.Sources)
{
    # Write-Host $source.GetType()
    $hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
}
Run Code Online (Sandbox Code Playgroud)

Bac*_*its 5

正如@VivekKumarSingh 的评论所暗示的那样,这是一个与加速器相关的错误

这将不起作用:

# Error
$y = [System.Management.Automation.PSCustomObject]@{Path='some path string here'; Pack=$False}
Run Code Online (Sandbox Code Playgroud)

这将不起作用:

$y = [PSCustomObject]@{Path='some path string here'; Pack=$False}

function t ([System.Management.Automation.PSCustomObject]$x) { $x }

# Error
t $y
Run Code Online (Sandbox Code Playgroud)

这将起作用:

$y = [PSCustomObject]@{Path='some path string here'; Pack=$False}

function t ([PSCustomObject]$x) { $x }

t $y
Run Code Online (Sandbox Code Playgroud)

但是,以上不会将任何类型转换为 a PSCustomObject,因为该类型继承自Object

PS> function t ([PSCustomObject]$x) { $x.GetType().FullName }
PS> t 5
System.Int32
PS> t 'asdf'
System.String
PS> t $(Get-ChildItem)
System.Object[]
PS> t $(Get-Item .)
System.IO.DirectoryInfo
Run Code Online (Sandbox Code Playgroud)

这也可以,但我不完全确定它是否 100% 等效。

function t ([System.Management.Automation.PSObject]$x) { $x }
Run Code Online (Sandbox Code Playgroud)

我不确定的原因是因为这种奇怪:

PS> $a = New-Object -TypeName System.Management.Automation.PSObject -Property @{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Management.Automation.PSCustomObject

PS> $a = New-Object -TypeName System.Management.Automation.PSCustomObject -Property @{Path='some path string here'; Pack=$False}
New-Object : A constructor was not found. Cannot find an appropriate constructor for type System.Management.Automation.PSCustomObject.

PS> $a = [PSCustomObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Management.Automation.PSCustomObject

PS> $a = [System.Management.Automation.PSObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Collections.Hashtable

PS> $a = [PSObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Collections.Hashtable
Run Code Online (Sandbox Code Playgroud)

据我所知,[PSCustomObject][PSObject]对于两个加速器System.Management.Automation.PSObjectSystem.Management.Automation.PSCustomObject只是他们添加的一个实现细节[PSCustomObject],但不幸的是,一切工作的方式感觉有点不一致。但是,我并不完全清楚[PSObject]类型加速器的用途。它似乎什么都不做,但它也确实存在:

PS> ([System.Management.Automation.Cmdlet]).Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get.ContainsKey('psobject')
True
Run Code Online (Sandbox Code Playgroud)