Позиционное связывание и наборы параметров - PullRequest
0 голосов
/ 17 апреля 2020

Я изо всех сил пытаюсь понять поведение наборов параметров и позиционной привязки. Вот пример функции.

function Test-PositionBinding {
    [CmdletBinding(DefaultParameterSetName = 'ParamSet2')]
    param (
        [Parameter(ParameterSetName='ParamSet1',Position = 0)]
        [int]
        $param1,

        [Parameter(ParameterSetName='ParamSet1',Position = 1)]
        [int]
        $param2,

        [Parameter(ParameterSetName='ParamSet2',Position = 0)]
        [int]
        $param3
    )    
    process {
        $PSCmdlet.ParameterSetName
        $param1
        $param2
        $param3
    }
}

Основываясь на выводе справки, может показаться, что при вызове функции с одним int должен использоваться paramset1, а при вызове с 2 int должен использоваться paramset2, чего я и ожидал.

SYNTAX
    Test-PositionBinding [[-param3] <int>] [<CommonParameters>]

    Test-PositionBinding [[-param1] <int>] [[-param2] <int>] [<CommonParameters>]

Однако я получаю следующий вывод.

PS C:\> Test-PositionBinding 1
ParamSet2
0
0
1
PS C:\> Test-PositionBinding 1 2

Test-PositionBinding: A positional parameter cannot be found that accepts argument '2'.

Я ожидал бы следующее.

PS C:\> Test-PositionBinding 1 2
ParamSet1
1
2
0

Если мы изменим тип param1 на Строка, в которой функция работает, как и ожидалось.

PS C:\> Test-PositionBinding 1
ParamSet2

0
1
PS C:\> Test-PositionBinding 'abc'
ParamSet1
abc
0
0
PS C:\> Test-PositionBinding 'abc' 2
ParamSet1
abc
2
0

Что я не понимаю в том, как PS интерпретирует наборы параметров?

В конечном счете, мой вопрос, почему PS не может различить 2 набора параметров с позиционной привязкой и различным количеством параметров, если первый набор имеет одинаковый тип между наборами.

Ответы [ 2 ]

0 голосов
/ 19 апреля 2020

Согласно MS Docs:

Требования к набору параметров Следующие требования применяются ко всем наборам параметров.

Каждый набор параметров должен иметь хотя бы один уникальный параметр. Если возможно, сделайте этот параметр обязательным параметром.

Набор параметров, содержащий несколько позиционных параметров, должен определять уникальные позиции для каждого параметра. Никакие два позиционных параметра не могут указывать одну и ту же позицию.

Только один параметр в наборе может объявить ключевое слово ValueFromPipeline со значением true. Несколько параметров могут определять ключевое слово ValueFromPipelineByPropertyName со значением true.

Если для параметра не указан набор параметров, параметр принадлежит всем наборам параметров.

Это хорошо напиши на эту топи c, которая хранилась рядом и помогла мне. Отрезать это здесь, просто дать вам ссылку, на которую можно перейти. Хотя это не набор параметров, заданный c, применяются те же правила.

Указание положения параметра PowerShell

Для некоторых команд имеет смысл разрешить вам передавать вещи по положению, а не по имени, особенно в тех случаях, когда было бы немного путаницы, если имена параметров пропущены (как в этом примере).

function Test-Position
{
    [CmdletBinding()]
    Param
    (
        [parameter(Position=0)]$parm1,
        [parameter(Position=1)]$parm2,
        [parameter(Position=2)]$parm3,
        [parameter(Position=3)]$parm4
    )
}

Что что делать?

> Согласно справке (about_Functions_CmdletBindingAttribute), вы должны использовать необязательный аргумент PositionalBinding для атрибута CmdletBinding () и установить его в $ false.

Это приведет к тому, что все параметры по умолчанию не будут разрешены позицией. Затем> вы можете указать Позицию для любых (возможно, только одного или двух) параметров, которые вы будете использовать sh для позиции.

Например, это позволит использовать только $ parm1 для позиции:

function Test-Position
{
    [CmdletBinding(PositionalBinding = $false)]
    Param([parameter(Position=0)]$parm1,
                                    $parm2,
                                    $parm3,
                                    $parm4)
}

Но подождите, это становится проще

Даже несмотря на то, что в справке говорится, что все параметры являются позиционными по умолчанию, оказывается, что использование Position для одного параметра означает что вы должны использовать его для любых параметров, к которым вы хотите получить доступ по позиции.

Например, в этой версии функции я не указал ositionalBinding = $ False в атрибуте CmdletBinding, но только первый параметр доступен по позиции.

function Test-Position2
{
    [CmdletBinding()]
    Param
    (
        [parameter(Position=0)]$parm1, 
                                $parm2, 
                                $parm3, 
                                $parm4
    )
}

Это интересно для меня, так как кажется, что противоречит тому, что в справке. В частности, в справке говорится, что все параметры позиционные. Затем говорится, что для отключения этого значения по умолчанию вы должны использовать параметр PositionalBinding. Это показывает, что вам не нужно этого делать, если только вам не нужны никакие позиционные параметры.

В качестве последнего примера, просто чтобы убедиться, что мы понимаем, как используется значение Position, рассмотрим следующую функцию и справка по синтаксису:

function Test-Position3
{
    [CmdletBinding()]
    Param
    (
        $parm1,
        $parm2,
        [parameter(Position=1)]$parm3,
        [parameter(Position=0)]$parm4
    )
}

Включив Position в 2 параметра, мы обеспечили доступность двух других параметров только по имени. Кроме того, назначенные позиции отличаются от порядка, в котором параметры определены в функции, и это отражено в справке по синтаксису.

0 голосов
/ 17 апреля 2020

Если вы добавите IF, который вы увидите при выборе параметра 1 или 2, у вас будет набор параметров 1

, если вы выберете параметр 1 или 2, вы не сможете выбрать параметр 3 или 4

если вы запустите Test-postionbinding 1

Тогда, поскольку param1 определен как 0, PowerShell автоматически свяжет первый передаваемый функции параметр с позицией 0.
, если вы передадите 0 -param4 1
Param3 будет иметь значение 0, а param4 будет 1, и вы попадете в paramset2.

Если вы укажете param1, тогда вашим единственным другим параметром будет param2, потому что он является членом Paramset1

Если вы выберете param3, то единственным другим доступным параметром будет param4, потому что он является частью paramset2

function Test-PositionBinding {
    [CmdletBinding(DefaultParameterSetName = 'ParamSet2')]
    param (
        [Parameter(ParameterSetName='ParamSet1',Position = 0)]
        [int]
        $param1,

        [Parameter(ParameterSetName='ParamSet1',Position = 1)]
        [int]
        $param2,

        [Parameter(ParameterSetName='ParamSet2',Position = 0)]
        [int]
        $param3
    )    
    process {
        if($PSCmdlet.ParameterSetName -eq "paramset1")
        {
            write-output "Paramset1"
            $param1
            $param2
        }

        if($PSCmdlet.ParameterSetName -eq "paramset2")
        {
            write-output "Paramset2"
            $param3
            $param4
        }
    }
}

Наблюдение за привязкой позиции 2

Test-PositionBinding -param1 1 10
Paramset1
1
10

Наблюдение за paramset2

Test-PositionBinding -param3 10
Paramset2
10

без использования имен параметров и принудительное использование PowerShell для использования указанной привязки: Test-PositionBinding 0 1 Test-PositionBinding : Позиция

al parameter cannot be found that accepts argument '1'.
At line:1 char:1
+ Test-PositionBinding 0 1
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Test-PositionBinding], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Test-PositionBinding


PS C:\WINDOWS\system32> Test-PositionBinding 0
Paramset2
0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...