Параметры со значением по умолчанию не в PsBoundParameters? - PullRequest
8 голосов
/ 11 мая 2010

Общий код

Рассмотрим этот код:

PS> function Test { param($p='default value') $PsBoundParameters }
PS> Test 'some value'
Key                                                               Value
---                                                               -----
p                                                                 some value
PS> Test
# nothing

Я ожидаю, что $PsBoundParameters будет содержать запись для переменной $p в обоих случаях. Это правильное поведение?

Вопрос

Я бы хотел использовать splatting, который бы работал так для многих функций:

function SomeFuncWithManyRequiredParams {
  param(
    [Parameter(Mandatory=$true)][string]$p1,
    [Parameter(Mandatory=$true)][string]$p2,
    [Parameter(Mandatory=$true)][string]$p3,
  ...other parameters
  )
  ...
}
function SimplifiedFuncWithDefaultValues {
  param(
    [Parameter(Mandatory=$false)][string]$p1='default for p1',
    [Parameter(Mandatory=$false)][string]$p2='default for p2',
    [Parameter(Mandatory=$false)][string]$p3='default for p3',
  ...other parameters
  )
  SomeFuncWithManyRequiredParams @PsBoundParameters
}

Я не хочу вызывать SomeFuncWithManyRequiredParams со всеми перечисленными параметрами:

  SomeFuncWithManyRequiredParams -p1 $p1 -p2 $p2 -p3 $p3 ...

Возможно ли это?

Ответы [ 3 ]

5 голосов
/ 10 сентября 2014

Я знаю, что этот вопрос очень старый, но недавно мне нужно было что-то подобное (хотел сделать разбрызгивание с большим количеством параметров по умолчанию). Я придумал это, и это сработало очень хорошо:

$params = @{}
foreach($h in $MyInvocation.MyCommand.Parameters.GetEnumerator()) {
    try {
        $key = $h.Key
        $val = Get-Variable -Name $key -ErrorAction Stop | Select-Object -ExpandProperty Value -ErrorAction Stop
        if (([String]::IsNullOrEmpty($val) -and (!$PSBoundParameters.ContainsKey($key)))) {
            throw "A blank value that wasn't supplied by the user."
        }
        Write-Verbose "$key => '$val'"
        $params[$key] = $val
    } catch {}
}

Бесстыдный плагин впереди : Я решил превратить это в пост в блоге, в котором есть больше объяснений и пример сценария использования .

5 голосов
/ 12 мая 2010

Это зависит от того, как вы определяете «связанный», я думаю, т.е. это значение связано с пользовательским значением или значением по умолчанию, предоставленным функцией? Честно говоря, меня не удивляет, что он ведет себя так же, как и я, когда я вижу, что «ограниченный» означает первый - связанный с пользовательским вводом. В любом случае, вы можете решить эту проблему, установив переменную $ PSBoundParameters, например ::1001*

function SimplifiedFuncWithDefaultValues { 
  param( 
    [Parameter(Mandatory=$false)][string]$p1='default for p1', 
    [Parameter(Mandatory=$false)][string]$p2='default for p2', 
    [Parameter(Mandatory=$false)][string]$p3='default for p3', 
  ...other parameters 
  ) 
  if (!$PSBoundParameters.ContainsKey(p1))
  {
    $PSBoundParameters.p1 = 'default for p1'
  }
  # rinse and repeat for other default parameters.
  SomeFuncWithManyRequiredParams @PSBoundParameters 
} 
0 голосов
/ 02 августа 2014

Вы можете использовать вспомогательную функцию, аналогичную функции Add-Variable ниже:

function SimplifiedFuncWithDefaultValues {
    param(
        [Parameter(Mandatory=$false)][string]$p1='default for p1',
        [Parameter(Mandatory=$false)][string]$p2='default for p2',
        [Parameter(Mandatory=$false)][string]$p3='default for p3',
        ...other parameters
    )

    $PSBoundParameters | Add-Variable p1, p2, p3

    SomeFuncWithManyRequiredParams @PSBoundParameters 
}

function Add-Variable {
    param(
        [Parameter(Position = 0)]
        [AllowEmptyCollection()]
        [string[]] $Name = @(),
        [Parameter(Position = 1, ValueFromPipeline, Mandatory)]
        $InputObject
    )

    $Name |
    ? {-not $InputObject.ContainsKey($_)} |
    % {$InputObject.Add($_, (gv $_ -Scope 1 -ValueOnly))}
}
...