Repository navigation
ValidateSet should support a dynamically generated set #3744
Description
Activity
- addedWG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtimeIssue-Enhancementthe issue is more of a feature request than a bugthe issue is more of a feature request than a bugUp-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsUp-for-grabs issues are not high priorities, and may be opportunities for external contributors
on May 9, 2017 This is a much better solution. Well played Jason Shirk (@lzybkr) like it!
We should also consider binary cmdlets. One option is to accept a type that implements an interface, something like:
public interface IValidateSetGenerator { IEnumerable<string> Get(); } public class MyValidateSetGenerator : IValidateSetGenerator { public IEnumerable<string> Get() { yield return "Something"; } } ... [Parameter()] [ValidateSet(typeof(MyValidateSetGenerator)] public string Something { get; set; }
This could probably work in PowerShell too (the interface would be defined in System.Management.Automation.dll.
I think we'd need a way of passing
$PSBoundParametersto truly cover most of the scenarios where people are resorting to dynamic parameters today.Reacted by Mariusz PawelskiRecently I played with this and it seems like it might be too expensive due to IntelliSense.
powercode commented
on May 9, 2017 CollaboratorMore actionsIlya (@iSazonov) What is to expensive?
Staffan Gustafsson (@powercode) IntelliSense can call attributes very often. ValidateSet with script block becomes similar to ValidateScript (can run unpredictably long).
Perhaps we should do only IValidateSetGenerator (not script block) because we want support interfaces in PowerShell classes.
Also could we add IValidateSetGenerator not only in ValidateSet attribute: ValidateScript, ValidatePattern, ... for IntelliSense support?
Ilya (@iSazonov) I don't think that would be much of a problem. Most people know not to have long-running commands in intellisense code. People are already working around this issue using the less-friendly dynamicparam block and passing a ValidateSetAttribute to the attribute collection.
I feel the problem with using an interface for this is that a lot of PowerShell coders aren't programmers. It's one thing to support classes, it's another thing to force the user to use them. Just my opinion ofc. The 'PowerShell way' here is to support a ScriptBlock.
Jason Shirk (@lzybkr) would the following not be easier:
public interface IValidateSetGenerator { IEnumerable<string> Get(); } public class MyValidateSetGenerator : IValidateSetGenerator { public IEnumerable<string> Get() { yield return "Something"; } } [Parameter()] [ValidateSet(MyValidateSetGenerator)] public string Something { get; set; }
and just have a ValidateSet overload that takes in an IValidateSetGenerator, rather than using typeof?
So two new overloads for ValidateSetAttribute:
ValidateSetAttribute(ScriptBlock sb)
and
ValidateSetAttribute(IValidateSetGenerator g)
IValidateSetGenerator vs IValidateSetEnumerator ?
Reacted by LiamIlya (@iSazonov) maybe even IDynamicValidateSet?
Edit: Upon reflection I prefer IValidateSetEnumerator
It looks like it is from DynamicParams but it is not related directly. Also we have RFC for Dynamic Keywords so we should avoid "Dynamic" term to eliminate confusion.
Reacted by LiamLiam (@lfshr) - C# requires
typeof(MyValidateSetGenerator)becauseMyValidateSetGeneratoris not an expression.The interface name should probably not end in
Enumeratorbecause the interface does not define an enumerator.Reacted by LiamMaybe IValidateSetValuesGetter
3 remaining items
Is this still up for grabs? I'm looking for something small to start with.
update: never mind, I see the PR is in progress :)
Welcome to code review!
maybe you can help me out with my challange. I like to set ValidateSet to run my "example.ps1 -region eu-cental-1" and get the AWS regions
Eg:
Param(
[parameter(Mandatory=$true)]
[ValidateSet((Get-AWSRegion).region)]
[String[]]
$region
)process {
# do whatever
}vexx32 commented
on Nov 3, 2018 CollaboratorMore actionsI don't see any link to the relevant PR, but it appears to need a script block, so you would write:
[ValidateSet({ (Get-AwsRegion).Region })]Reacted by Rafael Camisonyou're right; it's not a PR; just a little script to automate my AWS stuff. Maybe I open one once it has some relevant features.
[ValidateSet({ (Get-AwsRegion).Region })]
this does not make any difference unfortunately
vexx32 commented
on Nov 3, 2018 CollaboratorMore actionsJason Shirk (@lzybkr) a PR is mentioned in this thread, but I don't see any links to it. Did this end up getting implemented?
You need to implement
IValidateSetValuesGenerator. See:
https://github.com/iSazonov/PowerShell/blob/65349de2b25022092213d86cfc1f5dfe0c92cbc6/test/powershell/Language/Classes/Scripting.Classes.Attributes.Tests.ps1#L273Reacted by Rain Sallow (/u/ta11ow)vexx32 commented
on Nov 4, 2018 CollaboratorMore actions@rafaelc81 see here for the example that was merged into documentation after the PR was merged.
Reacted by Mariusz PawelskiThe example in the docs looks nothing like the example the OP of this issue wanted. The OP asks for a script block, and the solution provided is a full on syntax-verbose class.
I can't get an example like the script block to work. Was that implemented or only the syntax-verbose class version?
If not, are there any plans to support the significantly more terse syntax? Should another issue be opened?
Thanks!
Josh Olson (@OlsonDev) The issue description is misleading. We only implemented a variant based on
IValidateSetValuesGeneratorinterface until we receive more feedback. Feel free open new issue with the description of the necessary feature.Reacted by Josh Olsonvexx32 commented
on Jan 15, 2019 CollaboratorMore actionsIndeed. It should be possible to borrow portions of the code from
[ArgumentCompleter()]for this purpose; it also takes a script block and apparently applies it to the method defined inIArgumentCompleterRain Sallow (/u/ta11ow) (@vexx32) There is samples in attributes.cs file how to use execution context. I assume that the tests will be most of this work and not the code itself. :-)
Reacted by Rain Sallow (/u/ta11ow)Ilya (@iSazonov) Rain Sallow (/u/ta11ow) (@vexx32) Thanks, I created the aforementioned issue here.
People often use dynamic parameters so they can dynamically generate a
ValidateSetattribute.We should provide a simpler way to do this. One option is to accept a scriptblock: