2016-10-06 63 views
3

考慮這個功能:爲什麼不能根據[string] vs [hashtable] vs [pscustomobject]來解析參數集?

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 [字符串]以PARAM [PsCustomObject]成功

這似乎是PowerShell是考慮[string]是一個[PsCustomObject]。但'string' -is [pscustomobject]評估爲$false

這一切都讓我有以下問題:

  1. 爲什麼不能PowerShell中選擇一個基於[string][pscustomobject]之間的類型的不同參數集?
  2. 原因是PowerShell認爲[string][pscustomobject]?如果是這樣,那爲什麼呢?
  3. 是否有解決方法,允許我使用不同的類型來選擇不同的參數集?
+0

據我所知,它被解析爲「String」和「PSObject」,這造成了簽名模糊性。因此錯誤記錄中的術語「AmbiguousParameterSet」。 – Eris

回答

2

我認爲原因是任何東西都可以鑄造到[PSObject][PSCustomObject])。 PowerShell嘗試將值合併到目標類型。這就是爲什麼當你有一個參數[int],你可以通過"5",它會工作,或者爲什麼當你有一個參數是[ipaddress],你可以給它一個字符串"1.2.3.4"

所以在參數綁定,發生了什麼,當你傳遞一個[string][hashtable]是,它成功地將它綁定到[pscustomboject]參數,以及其他的(至少)之一,因此它無法解析的設置。

我不認爲有任何方法可以關閉此行爲或使其「更嚴格」。


順便說一下,之所以什麼都可以鑄造到[PSObject]是因爲在PowerShell中,每一個對象是[PSObject]了!這也是爲什麼您可以將成員添加到任何對象的任何實例。 PowerShell使這一切都非常透明,這就是爲什麼如你所說,這違反了這個(以及其他一些情況)中最不讓人驚訝的原則。

如果你在C#中使用PowerShell進行交互,那麼所有包裹在[PSObject]中的事實會變得更加明顯(並且在很多情況下很煩人),這就是我第一次意識到這種情況。

+0

它似乎確實如此。如果是這樣的話,那確實違反了最不讓人驚訝的原則。 – alx9r

+0

@ alx9r我沒有時間提交答案,但我添加了一些額外的信息。 – briantist

+1

對於任何未來遇到此問題的人來說,值得注意的是['PSObject'和'PSCustomObject'關係非常密切,但可以產生不同的結果](https://stackoverflow.com/a/35894817/1404637)。 – alx9r