如何检查选择了 ValidateSet 的哪个值,而无需在块中将该值重新键入"if"文本?



是否有某种数组可以保存您为 ValidateSet 指定的所有值?我不想复制"if"块中关注的值来检查它是否等于用户选择的值。

让我们以以下示例为例:

function Get-MyValue
{ param([Parameter(Mandatory = $true)]
[ValidateSet("someLongLongOption1",
"someLongLongOption2",
"someLongLongOption3")]
[string]$myOption)
}

我现在能做的是检查选项2是否已被选中if($myOption -eq "someLongLongOption2")。但我想做的是:if($myOption -eq $ValidateSet[1]).如何做到这一点?

谢谢

更新:

在查看了 Mathias R. Jessen 的代码后,我研究了枚举参数,并通过向Add-Type注册枚举(这样不仅当您在函数名称后键入连字符时,参数由 ISE 列出,而且在该参数后键入空格后,您有 ISE 显示可供选择的枚举值列表(。但是现在有一个小问题:只有当您在"if"括号内[MyOptions]::someLongLongOption1枚举时,ENUM 才会被 ISE 识别,但如果您在switch内指定此条件,则无法识别枚举。因此,如果有人解释为什么会这样,我将不胜感激。

这是我的代码:

Add-Type -TypeDefinition @"
public enum MyOptions {
someLongLongOption1 = 1,
someLongLongOption2 = 2,
someLongLongOption3 = 3
}
"@
function Get-MyValue
{
param(
[Parameter(Mandatory=$true)]
[MyOptions]$MyOption
)
if([MyOptions]::someLongLongOption1 -eq $MyOption){
Write-Host "option 1"
}
else {Write-Host "some option other than option 1"}
}

现在,如果您调用函数Get-MyValue -MyOption someLongLongOption1则会得到option 1,当您以Get-MyValue -MyOption someLongLongOption2Get-MyValue -MyOption someLongLongOption3调用函数时,您会得到some option other than option 1

我担心的是,ISE在使用switch语句而不是if语句时无法识别MyOptions枚举。所以如果你把if语句替换为

switch($MyOption) {
[MyOptions]::someLongLongOption1{Write-Host "option 1"}
default{Write-Host "some option other than option 1"}
}

ISE不仅在输入::后不会显示枚举标识符列表,函数调用Get-MyValue -MyOption someLongLongOption1会求助于default语句而不是适当的语句。如果您知道此行为的原因,请告诉我。

谢谢

你能把ValidateSet的选项放到数组中吗?是的。它不漂亮,但你可以。

function Get-MyValue
{ 
param([Parameter(Mandatory = $true)]
[ValidateSet("someLongLongOption1",
"someLongLongOption2",
"someLongLongOption3")]
$myOption
)
$ValidateSet = $MyInvocation.
MyCommand.
Parameters["myOption"].
Attributes.
Where{$_ -is [System.Management.Automation.ValidateSetAttribute]}.
ValidValues;
if ($myOption -eq $ValidateSet[1]) {
"someLongLongOption2"
}
}

假设PowerShell版本5或更高版本,则可以改用enum类型:

function Get-MyValue
{
param(
[Parameter(Mandatory)]
[MyOptions]$MyOption
)
begin{
enum MyOptions {
someLongLongOption1 = 1
someLongLongOption2 = 2
someLongLongOption3 = 3
}
}
end {
if(1 -eq $MyOption){
# someLongLongOption1 was chosen
}
}
}

另一种选择是使用在脚本范围内引用数组的动态参数。 冗长,但应该支持ISE中的选项卡完成,并允许您按索引引用某些内容

#region: Module code
$script:getMyValueValidateSet = [String[]] @(
"someLongLongOption1",
"someLongLongOption2",
"someLongLongOption3"
)
Function Get-MyValue
{ 
[CmdletBinding()]
Param()
DynamicParam {
$parameters = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$myOptionParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
$myOptionParameterAttribute.Mandatory = $true
$myOptionParameterValidateSet = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $script:getMyValueValidateSet
$myOptionParameterAttributes = New-Object 'System.Collections.ObjectModel.Collection[System.Attribute]'
$myOptionParameterAttributes.Add($myOptionParameterAttribute)
$myOptionParameterAttributes.Add($myOptionParameterValidateSet)
$myOptionParameter = New-Object System.Management.Automation.RuntimeDefinedParameter -ArgumentList 'MyOption','String',$myOptionParameterAttributes
$parameters.Add('MyOption', $myOptionParameter)
return $parameters
}
Begin {
$MyOption = $PSBoundParameters['MyOption']
}
Process {
$private:i = [Array]::IndexOf($script:getMyValueValidateSet, $MyOption)
Write-Verbose "You chose: $MyOption, which was option #$private:i"
Write-Output $script:getMyValueValidateSet[$private:i]
}
}
#endregion
#region: Test code
Write-Host "`n`nTest help..."
Get-Help Get-MyValue -Detailed
Write-Host "`n`nTest invalid..."
Get-MyValue -MyOption NotValid
Write-Host "`n`nTest valid..."
Get-MyValue -MyOption someLongLongOption2
#endregion

创建动态参数的开销是大于还是小于验证集的重复,由您决定。

DynamicParam的用例实际上是用于比这更多的动态功能,但可以哄骗它执行这个简单的数组查找。

而且,如果您将上述内容放入模块文件中(例如MyLibrary.psm1(,并在实际脚本的开头执行Import-Module .MyLibrary.psm1,您不会将数组泄漏到调用代码(因为脚本作用域是"模块"作用域(,但仍然可以从您在 MyLibrary.psm1文件中定义的函数中引用数组。

最新更新