How to create a Converter for an Enum

81 views Asked by At

How to create (preferably in PowerShell) a type converter for a custom PowerShell [enum]?

Related PowerShell issue: enum <enum-name> should ConvertFrom [string]

Based on the specific [Access] example in question How to define a type of a bit-combination?:

[Flags()] enum Access {
    Execute = 1
    Write = 2
    Read = 4
}

I am trying to build an [Access] ConvertFrom converter:

class AccessConverter : System.Management.Automation.PSTypeConverter
{
    [bool] CanConvertFrom([object]$sourceValue, [Type]$destinationType) {
        return $sourceValue -eq [string]
    }
    [object] ConvertFrom([object]$sourceValue, [Type]$destinationType, [IFormatProvider]$formatProvider, [bool]$ignoreCase) {
        if     ($sourceValue -eq [string]) { return [Access]$SourceValue }
        else { throw [NotImplementedException]::new() }
    }
    [bool] CanConvertTo([object]$sourceValue, [Type]$destinationType) {
        return $false
    }
    [object] ConvertTo([object]$sourceValue, [Type]$destinationType, [IFormatProvider]$formatProvider, [bool]$ignoreCase) {
        throw [NotImplementedException]::new() 
    }
}

Update-TypeData -TypeName Access -TypeConverter AccessConverter

But that doesn't work as expected:

$Access.HasFlag('read, write')

MethodException: Cannot convert argument "flag", with value: "read, write", for "HasFlag" to type "System.Enum": "Cannot convert value "read, write" to type "System.Enum". Error: "Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.""

Or is that because HasFlag expects a general enumType type rather then the specific custom ("access") enum?

1

There are 1 answers

2
Santiago Squarzon On BEST ANSWER

Not sure if this would work with a PSTypeConverter or if it even relates, what you're looking to accomplish, as I see it, can be achieved by overriding the .HasFlag method from your enum with a script method that casts your type:

[Flags()] enum Access {
    Execute = 1
    Write = 2
    Read = 4
}

$updateTypeDataSplat = @{
    TypeName   = 'Access'
    MemberType = 'ScriptMethod'
    MemberName = 'HasFlag'
    Value      = {
        param([Access] $flag)

        $this.PSBase.HasFlag($flag)
    }
}

Update-TypeData @updateTypeDataSplat

$access = [Access] 'Execute, Read'
$access.HasFlag('Execute, Read')         # true
$access.HasFlag('Execute, Write, Read')  # false