2010-05-11 5 views
8

Code généralParamètres avec la valeur par défaut pas dans PsBoundParameters?

Tenir compte de ce code:

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

j'attendre à ce que $PsBoundParameters contiendrait record pour la variable $p sur les deux cas. Est-ce que c'est un comportement correct?

Question

Je voudrais utiliser splatting qui fonctionnerait comme ça pour beaucoup de fonctions:

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 
} 

Je ne veux pas appeler SomeFuncWithManyRequiredParams avec tous les params énumérés:

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

Est-ce possible?

+0

Il y a deux questions que je dois poser ici, pour chaque paramètre en question: Pourquoi SomeFunc n'a-t-il pas la même valeur par défaut que SimplifiedFunc? Et, si les valeurs par défaut doivent être différentes, alors pourquoi SimplifiedFunc permet à l'utilisateur de surcharger la valeur par défaut (puisque, dans ce cas, ils pourraient simplement appeler SomeFunc directement pour surcharger)? – jpaugh

Répondre

5

Cela dépend de la manière dont vous définissez "bound". Je suppose que la valeur est liée à une valeur fournie par l'utilisateur ou à une valeur par défaut fournie par la fonction. Honnêtement, cela ne me surprend pas qu'il se comporte de la façon dont il le fait car je considère que "lié" signifie le premier - lié à l'entrée de l'utilisateur. Quoi qu'il en soit, vous pouvez résoudre ce problème en patcher la variable PSBoundParameters de $, par exemple:

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, je suis d'accord que '$ PSBoundParameters' peut contenir uniquement des arguments explicitement fournis, dépend de la définition. Ensuite, il devrait y avoir un moyen d'obtenir * tous les paramètres et valeurs * comme je l'avais prévu. – stej

+0

Considérant la solution que vous proposez: votre code est plus long que 'SomeFuncWithManyRequiredParams -p1 $ p1 -p2 $ p2 -p3 $ p3'. Et si tous les params dans la fonction 'SimplifiedFuncWithDefaultValues' ont des valeurs par défaut alors il n'y a pas de différence, je pense. – stej

+0

Je ne vois pas un moyen d'obtenir l'information que vous voulez via une variable automatique. Peut-être que vous pourriez vouloir déposer une suggestion MS Connect. –

0

Vous pouvez utiliser une fonction d'assistance similaire à la fonction Add-Variable ci-dessous:

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

Je sais que cette question est très ancienne, mais J'avais besoin de quelque chose comme ça récemment (je voulais faire du splatting avec beaucoup de paramètres par défaut). Je suis venu avec cela et cela a fonctionné très 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 {} 
} 

Shameless plug avant: J'ai décidé de transformer cela en une blog post which has more explanation and a sample usage script.

Questions connexes