Home > database >  PowerShell: How to accept an array of custom enum types as a function param?
PowerShell: How to accept an array of custom enum types as a function param?

Time:12-14

The example below is simply for illustration. I'm not looking for optimization or any sort of workaround solutions as this function obviosuly doesn't do anything useful - again, it's simply for presenting:

  • Accepting an entire enum type/structure as an argument
  • Doing something (anything) with the passed enum argument/param.
    • In this case it simply retrieves the enum name that corresponds to the int value of 2.

The following works to accept a single enum type as an argument and outputs the expected value:

function EnumTest
{
    param ([System.Object]$EnumObject)
    
    BEGIN {}
    PROCESS
    {
        [System.Enum]::GetName($EnumObject, 2)
    }
    END {}
}

enum MyCustomEnum
{
    Balloon     = 1
    Bicycle     = 2
    Cloud       = 3
}

enum MyOtherCustomEnum
{
    Crayon      = 1
    Dog         = 2
    Elephant    = 3
}

EnumTest -EnumObject MyCustomEnum

Output:

Bicycle



Questions:

  1. How can I get the param $EnumObject to accept an array of enum types (the entire enum structure, not just one of its names/values), e.g.:

    EnumTest -EnumObject MyCustomEnum, MyOtherCustomEnum

    • [System.Object[]]$EnumObject doesn't work
    • [System.Enum[]]$EnumObject doesn't work
      • Why doesn't this work?
    • [array]$EnumObject doesn't work
  2. What is the appropriate way to pass an entire enum type as an argument?

    • EnumTest -EnumObject MyCustomEnum appears to pass the enum structure's name "MyCustomEnum" as a string instead of the intended (entire) enum object [MyCustomEnum].

CodePudding user response:

PowerShell interprets the bare word token MyCustomEnum in this statement:

EnumTest -EnumObject MyCustomEnum

... as a string literal, no different than if you'd done:

EnumTest -EnumObject "MyCustomEnum"

If you just want to pass the type as a parameter argument, place a type literal in a subexpression like this:

EnumTest -EnumObject $([MyCustomEnum])

[object]/[System.Object] as parameter type will work here, since every type ultimately inherits from [object] anyway.

If you want to restrict parameter arguments to only types, use [type] as the parameter type:

function EnumTest
{
    param (
         [type]$EnumType
    )
    
    process {
        if($EnumType.IsEnum){
            [System.Enum]::GetName($EnumObject, 2)
        }
    }
}

If you want to pass an arbitrary number of enums either as positional arguments or via the pipeline, add an appropriate [Parameter()] attribute and (for trailing argument support) change the parameter type to an array of [type]:

function EnumTest
{
    param (
        [Parameter(ValueFromPipeline, ValueFromRemainingArguments)]
        [type[]]$EnumType
    )
    
    process {
        foreach($type in $EnumType){
            if($type.IsEnum){
                [System.Enum]::GetName($type, 2)
            }
        }
    }
}

Now all of the below invocation scenarios will work:

EnumTest $([MyCustomEnum]) $([MyOtherCustomEnum]) 
# or 
EnumTest @([MyCustomEnum], [MyOtherCustomEnum]) 
# or
[MyCustomEnum],[MyOtherCustomEnum] |EnumTest 
# or 
$enumTypes = [MyCustomEnum],[MyOtherCustomEnum]
EnumTest -EnumType $enumTypes
# or, if you wanna get funky: 
$paramArgs = @{ EnumType = 'MyCustomEnum,MyOtherCustomEnum' -split ',' -as [type[]] }
EnumTest @paramArgs

A previous version of the question made it sound like the user wanted to store multiple enum values as a scalar value, hence this answer:

It looks like you'll want to decorate the enum type with the Flags attribute - this will allow you to store compound values:

[Flags()]
enum MyCustomEnum
{
    FirstName   = 1
    SecondName  = 2
    ThirdName   = 4
}

Now multiple flags can be stored in a single instance of MyCustomEnum:

PS ~> $value = [MyCustomEnum]'FirstName, ThirdName'
PS ~> $value.value__ # the instance now stores the value of `FirstName -bor ThirdName`
5

The presence or absence of each individually defined value can be interrogated with the Enum.HasFlag method:

PS ~> $value = [MyCustomEnum]'FirstName, ThirdName'
PS ~> $value.HasFlag('FirstName')
True
PS ~> $value.HasFlag('SecondName')
False
  • Related