Types/ValidateScript/Validate.ps1
<# .SYNOPSIS Validates an Object with a Script .DESCRIPTION Validates one or more objects against the .ScriptBlock of this attribute. If the .ScriptBlock does not return "falsey" value (`$false, 0`), the validation will pass. If there are no arguments passed, this's ErrorMessage starts with `$`, then the values produced by that expression will be validated. .EXAMPLE [ValidateScript]::new({$_ % 2}).Validate(1) # Should -Be $true .EXAMPLE [ValidateScript]::new({$_ % 2}).Validate(0) # Should -Be $false #> param() $allArguments = @($args | & { process { $_ } }) if ((-not $allArguments.Length) -and ($this.ErrorMessage -notmatch '^\$') ) { return } elseif (-not $allArguments.Length) { $allArguments = @( $ExecutionContext.SessionState.InvokeCommand.InvokeScript($this.ErrorMessage) | & { process { $_ } } ) } # Validating a Script is mostly simple, except for one fairly large gotcha. # In PowerShell, two wrongs ($false, $false) will be interpretered as $true # So, we want want to correct for this "two wrongs make a right". @( @( # Run the validate script for every argument foreach ($argument in $allArguments) { $_ = $psItem = $argument try { . $this.ScriptBlock $argument | . { process { $_ -as [bool] # and quickly determine if each item is truthy } } } catch { Write-Error -ErrorRecord $_ $false } } ) -as # and force the whole thing into a list, which we see if we can make into [bool[]] -eq # an array of booleans. $false # Then, PowerShell equality comparison will only return the $false items in the list ).Length -eq 0 # and if nothing is false, we're quite sure that two wrongs didn't make a right, and that our validation passed. |