2010-05-11 23 views
8

Código generalParámetros con valor predeterminado no en PsBoundParameters?

consideran este código:

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

yo esperaría que $PsBoundParameters contendría récord para $p variables en ambos casos. ¿Es ese comportamiento correcto?

Pregunta

Me gustaría utilizar splatting que trabajaría como esto para una gran cantidad de funciones:

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 
} 

no quiero llamar SomeFuncWithManyRequiredParams con todos los parametros enumerados:

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

¿Es posible?

+0

Hay dos preguntas que debería hacer aquí, para cada parámetro en cuestión: ¿Por qué SomeFunc no tiene el mismo valor predeterminado que SimplifiedFunc? Y, si los valores predeterminados deben ser diferentes, ¿por qué SimplifiedFunc permite al usuario anular el valor predeterminado (ya que, en ese caso, simplemente podrían llamar a SomeFunc para sobrescribir)? – jpaugh

Respuesta

5

Depende de cómo defina "encuadernado" Supongo, por ejemplo, que el valor está vinculado a un valor proporcionado por el usuario o un valor predeterminado proporcionado por la función? Honestamente, no me sorprende que se comporte de la manera en que lo hace, ya que veo que "obligado" significa lo primero, atado de la entrada del usuario. De todos modos, puede resolver esto mediante parcheo la variable $ PSBoundParameters por ejemplo:

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

Ok, acepto que '$ PSBoundParameters' solo puede contener argumentos proporcionados explícitamente, depende de la definición. Entonces debería haber una forma de obtener * todos los parámetros y valores * como esperaba. – stej

+0

Considerando la solución que propone: su código es más largo que 'SomeFuncWithManyRequiredParams -p1 $ p1 -p2 $ p2 -p3 $ p3'. Y si todos los parámetros de la función 'SimplifiedFuncWithDefaultValues' tienen valores predeterminados, entonces no hay diferencia, creo. – stej

+0

No veo una forma de obtener la información que desea a través de una variable automática. Quizás desee presentar una sugerencia de MS Connect. –

0

se puede utilizar una función de ayuda similar a la función Add-Variable a continuación:

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))} 
} 
5

Sé que esta pregunta es muy antiguo, pero Necesitaba algo como esto recientemente (quería hacer splatting con muchos parámetros predeterminados). Se me ocurrió esto y funcionó muy bien:

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

Enchufe desvergonzado por delante: decidí convertir esto en un blog post which has more explanation and a sample usage script.

Cuestiones relacionadas