2010-05-11 18 views
8

codice generaleParametri con valore predefinito non in PsBoundParameters?

Considerate questo codice:

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

Mi aspetterei che $PsBoundParameters conterrebbe record per $p variabile su entrambi i casi. È un comportamento corretto?

Domanda

Mi piacerebbe usare splatting che avrebbe funzionato in questo modo per un sacco di funzioni:

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 
} 

Non voglio chiamare SomeFuncWithManyRequiredParams con tutti i params enumerati:

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

è possibile?

+0

Ci sono due domande che dovrei chiedere qui, per ogni parametro in questione: Perché SomeFunc non ha lo stesso valore predefinito di SimplifiedFunc? E, se i valori predefiniti devono essere diversi, allora perché SimplifiedFunc consente all'utente di ignorare il valore predefinito (poiché, in tal caso, potrebbero semplicemente chiamare SomeFunc direttamente per sovrascrivere)? – jpaugh

risposta

5

Dipende da come si definisce "associato" Immagino che il valore sia legato a un valore fornito dall'utente o un valore predefinito fornito dalla funzione? Onestamente, non mi sorprende che si comporta come fa io visto "legato" per significare il precedente - vincolato dall'input dell'utente. In ogni caso, è possibile risolvere questo problema patching del $ PSBoundParameters ad esempio variabile:

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, sono d'accordo che '$ PSBoundParameters' può contenere solo argomenti esplicitamente forniti, dipende dalla definizione. Quindi dovrebbe esserci un modo per ottenere * tutti i parametri e i valori * come mi aspettavo. – stej

+0

Considerando la soluzione che proponi: il tuo codice è più lungo di 'SomeFuncWithManyRequiredParams -p1 $ p1 -p2 $ p2 -p3 $ p3'. E se tutti i parametri nella funzione 'SimplifiedFuncWithDefaultValues' hanno valori predefiniti allora non c'è differenza, penso. – stej

+0

Non vedo un modo per ottenere le informazioni desiderate tramite una variabile automatica. Forse potresti voler presentare un suggerimento di MS Connect. –

0

è possibile utilizzare una funzione di supporto simile alla funzione Add-Variable di seguito:

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

So che questa domanda è molto vecchio, ma Avevo bisogno di qualcosa di simile di recente (volevo fare splatting con molti parametri di default). Sono venuto con questo e ha funzionato molto bene:

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

Shameless spina avanti: Ho deciso di trasformare questo in un blog post which has more explanation and a sample usage script.

Problemi correlati