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]の出力に次の行が含まれていることに気付きました。

arg [string] を param [PsCustomObject] にバインド成功

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 は、値をターゲットの型に結合しようとします。これが、 のパラメーターがある場合に[int]渡すことができ"5"、それが機能する理由、または のパラメーターがある場合[ipaddress]に string を与えることができる理由です"1.2.3.4"

そのため、パラメーターのバインディング中に[string]orを渡すと、それが(少なくとも) 他のパラメーターの 1 つと同様[hashtable]に、パラメーターに正常にバインドされているため、セットを解決できません。[pscustomboject]

この動作を無効にしたり、「より厳密」にしたりする方法はないと思います。


ちなみに、何でもキャストできる理由[PSObject]は、PowerShell ではすべてのオブジェクトが[PSObject]既に! これが、任意のオブジェクトの任意のインスタンスにメンバーを追加できる理由でもあります。PowerShellはこれをすべて本当に透過的にします。それが、あなたが言ったように、これ(および他のいくつかのケース)で最小の驚きの原則に違反した理由です。

C# 内から PowerShell を操作すると、すべてがラップされているという事実が[PSObject]より明白になります (そして、多くの場合、煩わしくなります)。

于 2016-10-06T18:57:29.850 に答える