Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optionally static class method for interface compatibility

Tags:

powershell

I've defined a custom ValidateSet parameter attribute like so:

Class MyValidValuesAttribute : System.Management.Automation.IValidateSetValuesGenerator {
    [string[]] GetValidValues() { return [string[]]'MyValidValueA','MyValidValueB' }
}

I'd like to avoid having to instantiate the class just to return the set of valid values.

I'd simply call [MyValidValuesAttribute]::GetValidValues() instead of the two-line

$X = [MyValidValuesAttribute]::new()
$Y = $X.GetValidValues()

but that method must not be static or the class will not implement the interface.

Is there any way to make a method work the same way regardless of whether the class has been instantiated under the same name? I know I could just implement GetValidValues_Static; wondering if a more elegant solution exists.

like image 771
alazyworkaholic Avatar asked Dec 18 '25 23:12

alazyworkaholic


1 Answers

As Santiago Squarzon points out, you don't usually need to instantiate an IValidateSetValuesGenerator-implementing class yourself: PowerShell does it for you when you use such a class in a [ValidateSet()] attribute in order to decorate a parameter in a function's or script's parameter-declaration block (param(...)), so as to constrain the arguments passed to that parameter to the set of values returned from the specified class' .GetValidValues() instance method.

Note: The IValidateSetValuesGenerator interface requires PowerShell (Core) v6+; for solutions that also work in Windows PowerShell, see this blog post that Santiago found.


If you do need to instantiate such a class explicitly:

instead of the two-line

You can use a single(-line) expression:

[MyValidValuesAttribute]::new().GetValidValues()

I know I could just implement GetValidValues_Static; wondering if a more elegant solution exists.

If you do need to keep the invocation ceremony to a minimum, you can declare a static property as follows, which then allows you to call [MyValidValuesAttribute]::ValidValues:

Class MyValidValuesAttribute : System.Management.Automation.IValidateSetValuesGenerator {
  static [string[]] $ValidValues = [MyValidValuesAttribute]::new().GetValidValues()
  [string[]] GetValidValues() { return [string[]] ('MyValidValueA','MyValidValueB') }
}

Caveat: Since the static ValidValues property is only initialized once, the above assumes that that the set of valid values is static, which may be at odds with the intentionally dynamic nature of the IValidateSetValuesGenerator interface.

  • In fact, the dynamic nature is the reason that the interface defines .GetValidValues() as an instance method - situationally, a different set of valid values may be returned; otherwise, you could simply use the [ValidateSet()] attribute with a static list of values, such as [ValidateSet('MyValidValueA', 'MyValidValueB')]

As of v7.2.1, PowerShell doesn't support property getters that are called on each invocation - see GitHub issue #2219.

like image 63
mklement0 Avatar answered Dec 20 '25 17:12

mklement0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!