为什么不能根据[string] vs [hashtable] vs [pscustomobject]来解析参数集?

时间:2016-10-06 17:29:00

标签: powershell pipeline parameterbinding parameter-sets

考虑这个功能:

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]无法正确解析。

我在解释the output from Trace-Command时没有经验。我注意到[string]的输出包括这一行:

  

BIND arg [string] to param [PsCustomObject] SUCCESSFUL

PowerShell似乎认为[string][PsCustomObject]。但'string' -is [pscustomobject]评估为$false

这给我留下了以下问题:

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

1 个答案:

答案 0 :(得分:2)

我认为原因是任何事情都可以投放到[PSObject][PSCustomObject])。 PowerShell尝试将值合并到目标类型。这就是为什么当你有一个[int]的参数时,你可以传递"5"它会起作用,或者为什么当你有一个[ipaddress]的参数时,你可以给它一个字符串{{ 1}}。

因此,在参数绑定期间,传递"1.2.3.4"[string]时发生的情况是,它成功地将其绑定到[hashtable]参数,以及(至少)其中一个参数其他人,因此无法解决问题。

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

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

如果您在C#中与PowerShell交互,那么所有内容都包含在[PSObject]中的事实变得更加明显(并且在许多情况下令人讨厌),这就是我第一次意识到这种情况。