Mark
Mark

Reputation: 339

Repeating array for ValidateSet

Given this basic function-skeleton:

Function Set-FruitSupply {
  [CmdletBinding()]
  Param (
    [Parameter(Mandatory=$False)][ValidateSet('Apples','Pears','Oranges')][String]$City,
    [Parameter(Mandatory=$False)][ValidateSet('Apples','Pears','Oranges')][String]$County,
    [Parameter(Mandatory=$False)][ValidateSet('Apples','Pears','Oranges')][String]$State
  )
  Begin {}
  Process {
    Switch ($PSBoundParameters.Keys) {
      'City'   { Write-Output -InputObject "The city has $City"   }
      'County' { Write-Output -InputObject "The city has $County" }
      'State'  { Write-Output -InputObject "The city has $State"  }
    }
  }
  End {}
}

I don't like the idea of having to repeat myself, so I would like to replace those 3 ValidateSets with a placeholder so I only have to type Apples, Pears and Oranges once. A variable doesn't work as far as I know.

Since I'm using PwSh 7, I tried creating a class.

class Fruit : System.Management.Automation.IValidateSetValuesGenerator {
  [System.String[]] GetValidValues() {
    $Fruits = @('Apples', 'Pears', 'Oranges')
    Return $Fruits
  }
}

Placing that above the function in question and using ValidateSet([Fruit]). This doesn't seem to work. I figured it ought to work with static data as well as dynamic data, maybe I'm just doing something wrong.

Does anybody know the correct way of doing this so I only have to write my set once?

Upvotes: 0

Views: 288

Answers (1)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174475

I can't seem to reproduce your issue with IValidateSetValuesGenerator, this works perfectly in 7.0 for me (I couldn't resist the temptation to make the parameters mutually exclusive), alternatives below:

class Fruit : System.Management.Automation.IValidateSetValuesGenerator {
  [System.String[]] GetValidValues() {
    $Fruits = @('Apples', 'Pears', 'Oranges')
    Return $Fruits
  }
}

Function Set-FruitSupply {
  [CmdletBinding()]
  Param (
    [Parameter(Mandatory=$False, ParameterSetName='City')]
    [ValidateSet([Fruit])]
    [String]$City,

    [Parameter(Mandatory=$False, ParameterSetName='County')]
    [ValidateSet([Fruit])]
    [String]$County,

    [Parameter(Mandatory=$False, ParameterSetName='State')]
    [ValidateSet([Fruit])]
    [String]$State
  )

  Begin {}
  Process {
    Switch ($PSCmdlet.ParameterSetName) {
      'City'   { Write-Output -InputObject "The city has $City"   }
      'County' { Write-Output -InputObject "The county has $County" }
      'State'  { Write-Output -InputObject "The state has $State"  }
    }
  }
  End {}
}

But if you can't get it to work (or you need a 5.1-compatible alternative), here are two options:

Option 1: Use a custom enum

enum Fruit {
  Apples
  Bananas
  Pears
}

function Set-FruitSupply
{
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$False, ParameterSetName='City')]
    [Fruit]$City,

    [Parameter(Mandatory=$False, ParameterSetName='County')]
    [Fruit]$County,

    [Parameter(Mandatory=$False, ParameterSetName='State')]
    [Fruit]$State
  )

  # ...
}

In this example we've avoided the duplicate list by validating against the defined Fruit enum type instead


Option 2: use a separate positional parameter for the validated values

function Set-FruitSupply
{
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$False, ParameterSetName='City')]
    [switch]$City,

    [Parameter(Mandatory=$False, ParameterSetName='County')]
    [switch]$County,

    [Parameter(Mandatory=$False, ParameterSetName='State')]
    [switch]$State,

    [Parameter(Mandatory=$true, Position = 0, DontShow = $true)]
    [ValidateSet('Apples','Pears','Oranges')]
    [string]$Fruit
  )

  # use `$Fruit` in here regardless of paramset
}

In this case, -Fruit itself won't autocomplete thanks to the DontShow flag, but it's values will, given that no other positional parameter exists, allowing you to complete and pass values with the same syntax: ie. Set-FruitSupply -City Apples.

Nice thing about this is that it works with version older than PowerShell 5 as well

Upvotes: 2

Related Questions