Почему нельзя определить наборы параметров на основе [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]
решить правильно.
У меня нет опыта в интерпретации выходных данных Trace-Command. Я заметил выход для [string]
включает в себя эту строку:
BIND arg [string] to param [PsCustomObject] УСПЕШНО
Кажется, что PowerShell рассматривает [string]
быть [PsCustomObject]
, Но 'string' -is [pscustomobject]
оценивает $false
,
Это все оставляет меня со следующими вопросами:
- Почему PowerShell не может выбрать набор параметров на основе различий в типе между
[string]
и[pscustomobject]
? - Причина в том, что PowerShell считает
[string]
быть[pscustomobject]
? Если так, то почему? - Есть ли обходной путь, который позволяет мне использовать разные типы для выбора разных наборов параметров?
1 ответ
Я считаю, что причина этого заключается в том, что все [PSObject]
([PSCustomObject]
). PowerShell пытается объединить значения с целевым типом. Вот почему, когда у вас есть параметр, который [int]
, вы можете пройти "5"
и это будет работать, или почему, когда у вас есть параметр, который [ipaddress]
Вы можете дать ему строку "1.2.3.4"
,
Итак, во время привязки параметров, что происходит, когда вы передаете [string]
или же [hashtable]
является то, что он успешно связывает его с [pscustomboject]
параметр, а также (по крайней мере) один из других, и, следовательно, он не может разрешить набор.
Я не верю, что есть какой-либо способ отключить это поведение или сделать его "более строгим".
И, кстати, причина может быть приведена к чему угодно [PSObject]
потому что в PowerShell каждый объект [PSObject]
уже! По этой же причине вы можете добавлять элементы к любому экземпляру любого объекта. PowerShell делает все это действительно прозрачным, поэтому, как вы сказали, он нарушил принцип наименьшего удивления в этом (и некоторых других случаях).
Если вы взаимодействуете с PowerShell изнутри C#, тот факт, что все обернуто в [PSObject]
становится намного более очевидным (и во многих случаях раздражающим), и именно так я впервые понял, что это так.