Home > front end >  Optionally static class method for interface compatibility
Optionally static class method for interface compatibility

Time:01-24

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.

CodePudding user response:

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.

  •  Tags:  
  • Related