代码之家  ›  专栏  ›  技术社区  ›  stej

默认值不在PsBoundParameters中的参数?

  •  8
  • stej  · 技术社区  · 15 年前

    通用代码

    请考虑以下代码:

    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 回复  |  直到 15 年前
        1
  •  5
  •   Keith Hill    15 年前

    这取决于您如何定义“bound”,我猜是从用户提供的值绑定的值还是由函数提供的默认值?老实说,它的行为方式并不奇怪,因为我认为“绑定”是指用户输入的前一个绑定。无论如何,您可以通过修补$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 
    } 
    
        2
  •  5
  •   briantist    11 年前

    我知道这个问题已经很老了,但是我最近需要这样的东西(想用很多默认参数来处理splatting)。我想到了这个,效果很好:

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

    无耻的插头在前面 :我决定把它变成 blog post which has more explanation and a sample usage script .

        3
  •  0
  •   drowa    11 年前

    您可以使用类似于 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))}
    }
    
        4
  •  0
  •   Mike Veazie - MSFT    6 年前

    这就是我喜欢做的:

    foreach($localP in $MyInvocation.MyCommand.Parameters.Keys)
    {
        if(!$PSBoundParameters.ContainsKey($localP))
        {
            $PSBoundParameters.Add($localP, (Get-Variable -Name $localP -ValueOnly))
        }        
    }
    
    推荐文章