Я наблюдаю какое-то странное поведение в пользовательской функции, которую я написал, и поэтому я написал несколько быстрых тестовых функций с различными характеристиками, чтобы продемонстрировать это поведение. Проблема возникает, когда наборы параметров достаточно похожи, и единственным отличительным фактором является тип объекта, полученного через конвейер.
Во-первых, я сделал простой тип, который служит только для того, чтобы отличаться от строки.
Add-Type @"
public class TestType {
public string Prop1;
}
"@
Затем я создал тестовую функцию и запустил ее со строковыми входными данными и входными данными TestType.
function Test-ParameterSets1
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Str")] [string] $StringInput,
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Test")] [TestType] $TestInput
)
begin {
$result = New-Object Object | Select-Object –Property @{n='FunctionName';e={$PSCmdlet.MyInvocation.InvocationName}},@{n='ParameterSetName';e={$PSCmdlet.ParameterSetName}}
}
process {
$result | Add-Member -MemberType NoteProperty -Name StringInput -Value $StringInput -PassThru | Add-Member -MemberType NoteProperty -Name TestInput -Value $TestInput
}
end {
$result
}
}
'string' | Test-ParameterSets1
New-Object TestType | Test-ParameterSets1
FunctionName ParameterSetName StringInput TestInput
------------ ---------------- ----------- ---------
Test-ParameterSets1 __AllParameterSets string
Test-ParameterSets1 __AllParameterSets TestType
В этом суть проблемы. ParameterSetName оценивается как __AllParameterSets
, хотя, как видно из значений, параметры установлены так, как ожидалось. Моя функция имеет множество наборов параметров и выполняет множество переключений на основе набора параметров для управления логическим потоком.
Затем я попытался добавить параметр, уникальный для одного набора параметров, и, как и ожидалось, ParameterSetName был правильным только для вызовов, в которых он был указан.
function Test-ParameterSets2
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Str")] [string] $StringInput,
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Test")] [TestType] $TestInput,
[Parameter(ParameterSetName="Test")] [string] $TestName
)
begin {
$result = New-Object Object | Select-Object –Property @{n='FunctionName';e={$PSCmdlet.MyInvocation.InvocationName}},@{n='ParameterSetName';e={$PSCmdlet.ParameterSetName}}
}
process {
$result | Add-Member -MemberType NoteProperty -Name StringInput -Value $StringInput -PassThru | Add-Member -MemberType NoteProperty -Name TestInput -Value $TestInput
}
end {
$result
}
}
'string' | Test-ParameterSets2
New-Object TestType | Test-ParameterSets2 -TestName MyName
New-Object TestType | Test-ParameterSets2
FunctionName ParameterSetName StringInput TestInput
------------ ---------------- ----------- ---------
Test-ParameterSets2 __AllParameterSets string
Test-ParameterSets2 Test TestType
Test-ParameterSets2 __AllParameterSets TestType
Затем я попытался добавить параметр, обязательный для обоих наборов параметров, и на этот раз ParameterSetName вычислялся как пустая строка, что особенно сбивало с толку.
function Test-ParameterSets5
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Str")] [string] $StringInput,
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Test")] [TestType] $TestInput,
[Parameter(Mandatory=$true, ParameterSetName="Str")] [Parameter(Mandatory=$true, ParameterSetName="Test")] [string] $Mandatory,
[Parameter(ParameterSetName="Test")] [string] $TestName
)
begin {
$result = New-Object Object | Select-Object –Property @{n='FunctionName';e={$PSCmdlet.MyInvocation.InvocationName}},@{n='ParameterSetName';e={$PSCmdlet.ParameterSetName}}
}
process {
$result | Add-Member -MemberType NoteProperty -Name StringInput -Value $StringInput -PassThru | Add-Member -MemberType NoteProperty -Name TestInput -Value $TestInput
}
end {
$result
}
}
'string' | Test-ParameterSets5 -Mandatory mandatoryParam
New-Object TestType | Test-ParameterSets5 -Mandatory mandatoryParam -TestName MyName
New-Object TestType | Test-ParameterSets5 -Mandatory mandatoryParam
FunctionName ParameterSetName StringInput TestInput
------------ ---------------- ----------- ---------
Test-ParameterSets5 string
Test-ParameterSets5 Test TestType
Test-ParameterSets5 TestType
Кажется, что PowerShell действительно знает, как правильно установить эти параметры, но ParameterSetName не выполняет правильную оценку. Есть ли способ заставить это работать? Я хотел бы избежать ненужных переключателей, таких как -String и -TestType, которые уникальны для своих собственных наборов параметров только для того, чтобы PowerShell мог выполнять свою работу. Спасибо!
ParameterSetName
в блокеbegin
до того, как функция сможет увидеть первый объект конвейера. Вместо этого вы должны сделать это в блокеprocess
. Каждый входной объект конвейера может привести к разнымParameterSetName
при вызове одной функции. - person user4003407   schedule 06.01.2018ParameterSetName
вprocess
может возвращать другое значение по сравнению со значением вbegin
, но OP не читаетParameterSetName
в блокеprocess
. - person user4003407   schedule 06.01.2018