10

通用代码

考虑这段代码:

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

我希望这$PsBoundParameters将包含$p两种情况下的变量记录。这是正确的行为吗?

问题

我想对很多功能使用可以像这样工作的飞溅:

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 ...

可能吗?

4

4 回答 4

7

我知道这个问题已经很老了,但我最近需要这样的东西(想要用很多默认参数进行喷溅)。我想出了这个并且效果很好:

$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 {}
}

无耻的插入:我决定把它变成一个博客文章,其中有更多的解释和一个示例使用脚本

于 2014-09-09T23:10:39.440 回答
5

这取决于您如何定义“绑定”我猜即是从用户提供的值或函数提供的默认值绑定的值?老实说,当我认为“绑定”意味着前者时,它的行为方式并不让我感到惊讶 - 来自用户输入的绑定。无论如何,您可以通过修补 $PSBoundParameters 变量来解决这个问题,例如:

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 
} 
于 2010-05-11T20:35:38.567 回答
2

这就是我喜欢做的事情:

foreach($localP in $MyInvocation.MyCommand.Parameters.Keys)
{
    if(!$PSBoundParameters.ContainsKey($localP))
    {
        $PSBoundParameters.Add($localP, (Get-Variable -Name $localP -ValueOnly))
    }        
}
于 2019-08-14T20:31:44.357 回答
0

您可以使用类似于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))}
}
于 2014-08-02T01:07:45.173 回答