Microsoft docs mention that if I apply the ValidateScript attribute to a collection, it will evaluate each element of the collection:
If this attribute is applied to a collection, each element in the collection must match the pattern.
I am trying to validate the collection itself. For example its type:
function testme {
param(
[ValidateScript({$_ -is [array] -or $_ -is [hashtable]}, ErrorMessage = "The item '{0}' did not pass validation of script '{1}'")]
[psobject]$args
)
}
$arr = [psobject]@("aaa", "bbb")
$arr -is [array] #returns True
testme -args $arr
This - as expected - nets me this result:
Cannot validate argument on parameter 'args'. The item 'aaa' did not pass validation of script '$_ -is [array] -or $_ -is [hashtable]'
I am not able to figure out how to match the input collection instead of the elements in the collection.
ValidateScript
derives from ValidateEnumeratedArgumentsAttribute
, as it name hints, arguments are enumerated and validated. If you want to validate a collection as a whole you'd need to go one level up and derive from ValidateArgumentsAttribute
however, there isn't a PowerShell built-in attribute decoration for this, you'd need to implement it yourself, here is a little example:
using namespace System.Management.Automation
class ValidateCollection : ValidateArgumentsAttribute {
[void] Validate([Object] $arguments, [EngineIntrinsics] $engineIntrinsics) {
# perhaps `$arguments -is [ICollection]` might do here
if ($arguments -is [array] -or $arguments -is [hashtable]) {
return
}
throw [MetadataException]::new(
"The item '$arguments' of type '$($arguments.GetType())' did not pass validation.")
}
}
Then for the usage you decorate your parameter like so:
function testme {
param(
[ValidateCollection()]
[psobject] $MyParameter
)
}
testme 1, 2, 3, 4 # passes test
testme @{ foo = 'bar' } # passes test
testme 1 # fails