3

考虑这个函数:

function Test-Discrimination
{
    [CmdletBinding()]
    param
    (
        [parameter(ValueFromPipeline = $true,
                    Mandatory = $true,
                    ParameterSetName = 'string')]
        [string]
        $String,

        [parameter(ValueFromPipeline = $true,
                    Mandatory = $true,
                    ParameterSetName = 'hashtable')]
        [hashtable]
        $Hashtable,

        [parameter(ValueFromPipeline = $true,
                    Mandatory = $true,
                    ParameterSetName = 'pscustomobject')]
        [pscustomobject]
        $PsCustomObject
    )
    process
    {
        $PSCmdlet.ParameterSetName
    }
}

管道[pscustomobject]的行为符合我的预期:

PS C:\> New-Object pscustomobject | Test-Discrimination
pscustomobject

但是,管道[string]会引发异常:

PS C:\> 'string' | Test-Discrimination
Test-Discrimination : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:12
+ 'string' | Test-Discrimination
+            ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (string:String) [Test-Discrimination], Paramete 
   rBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Test-Discrimination

也是如此[hashtable]

PS C:\> @{} | Test-Discrimination
Test-Discrimination : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:7
+ @{} | Test-Discrimination
+       ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (System.Collections.Hashtable:Hashtable) [Test- 
   Discrimination], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Test-Discrimination

添加DefaultParameterSetName='hastable'原因[hashtable]但无法[string]正确解决。

我在解释Trace-Command 的输出方面没有经验。我确实注意到输出[string]包括这一行:

BIND arg [string] 到参数 [PsCustomObject] SUCCESSFUL

这似乎 PowerShell 正在考虑[string]成为一个[PsCustomObject]. 但'string' -is [pscustomobject]评估为$false

这一切都给我留下了以下问题:

  1. [string]为什么 PowerShell 不能根据 a和 a的类型差异来选择参数集[pscustomobject]
  2. 原因是 PowerShell 认为 a[string]是 a[pscustomobject]吗?如果是这样,为什么会这样?
  3. 是否有一种解决方法可以让我使用不同的类型来选择不同的参数集?
4

1 回答 1

2

我相信这样做的原因是任何东西都可以转换为[PSObject]( [PSCustomObject])。PowerShell 尝试将值合并到目标类型。这就是为什么当你有一个参数 that's[int]时,你可以传递"5"它并且它会起作用,或者为什么当你有一个参数 that's[ipaddress]时,你可以给它一个 string "1.2.3.4"

[string]因此,在参数绑定期间,当您传递 a or时发生的情况[hashtable]是它成功地将其绑定到[pscustomboject]参数以及(至少)其他参数之一,因此它无法解析集合。

我不相信有任何方法可以关闭这种行为或使其“更严格”。


顺便说一句,任何东西都可以转换成的原因[PSObject]是因为在 PowerShell 中,每个对象都[PSObject]已经是!这也是您可以将成员添加到任何对象的任何实例的原因。PowerShell 使这一切变得非常透明,这就是为什么正如您所说,它在这种情况下(以及其他一些情况)违反了最小意外原则。

如果您从 C# 中与 PowerShell 进行交互,所有内容都包含在其中的事实[PSObject]会变得更加明显(并且在许多情况下很烦人),这就是我第一次意识到情况就是这样的原因。

于 2016-10-06T18:57:29.850 回答