O PowerShell oferece suporte a scripts de validação para variáveis. Isso é mais comumente usado para validar parâmetros de função, mas pode ser aplicado a qualquer variável. Esses scripts de validação são executados sempre que o valor da variável é alterado.
# create a variable with a validation script
[ValidateScript({
if (-not ($_.Length -in @(8, 16, 24))) {
Write-Host 'Validate Failed'
throw "Value '$_' has invalid length: $($_.Length)"
} else {
Write-Host 'Validate Success'
}
$true
})][System.String]$MyValidatedArg = "a" * 8 # prints "Validate Success"
# Each one of these will trigger the validation script
Write-Host "Several valid assignments..."
$MyValidatedArg = "b" * 8 # prints "Validate Success"
$MyValidatedArg = "b" * 8 # prints "Validate Success"
$MyValidatedArg = "b" * 16 # prints "Validate Success"
$MyValidatedArg = "b" * 24 # prints "Validate Success"
Se eu atribuísse um valor inválido à variável, isso geraria uma exceção
$MyValidatedArg = "foo" # throws an exception
Estranhamente, consigo ignorar o script de validação se eu especificar novamente a restrição de tipo durante a atribuição. Sei que "simplesmente não faça isso" é uma opção, mas o ponto principal da minha pergunta é: por que isso funciona?
[System.String]$MyValidatedArg = "123456789" # works even though this value is invalid
A princípio, pensei que fosse apenas um sombreamento de variáveis. Tipo, talvez eu estivesse criando uma segunda variável, objeto ou algo assim, especificando a restrição de tipo uma segunda vez. Tentei capturar uma referência à variável para ver se ela manteria o script de validação. Não mantém, mas não estou muito familiarizado com os detalhes internos do PowerShell para saber se este é um teste válido.
# create a reference and assign through the reference
Write-Host "Assigning through reference..."
$refToParameter = [ref] $MyValidatedArg
$refToParameter.Value = "c" * 24 # prints "Validate Success"
Write-Host " Read via variable: $MyValidatedArg"
Write-Host " Read via reference: $($refToParameter.Value)"
# the reference and the variable are linked
# Assignments to either trigger the validation script
Write-Host "Assigning through normal variable again..."
$MyValidatedArg = "d" * 24 # prints "Validate Success"
Write-Host " Read via variable: $MyValidatedArg"
Write-Host " Read via reference: $($refToParameter.Value)"
# This works, which is odd
Write-Host "Assigning with [System.String]..."
[System.String]$MyValidatedArg = "123456789" # invalid, nothing printed
Write-Host " No exceptions yet!"
# I thought this was some sort of variable shadowing thing, but the reference shows the new value too
Write-Host "The link between the variable and the reference is still there..."
$MyValidatedArg = "e" * 8 # valid, nothing printed
Write-Host " Read via variable: $MyValidatedArg"
Write-Host " Read via reference: $($refToParameter.Value)"
# and now we appear to have killed the validation script
Write-Host "Regular invalid assignment..."
$MyValidatedArg = "123456789" # invalid, nothing printed
Write-Host " It works now for some reason"
Da perspectiva interna, quando você cria uma nova variável, isso significa que um
PSVariable
objeto é adicionado aoVariable:
provedor , pequeno exemplo:O
PSVariable
objeto pode conter.Attributes
elementos que determinarão seu comportamento, por exemplo, na atribuição, pode ser transformação e validação . Se você quiser ver uma lista dos atributos existentes que podem ser adicionados, você pode fazer isso (observe que esta lista não está completa, você pode criar seus próprios atributos por herança):Com essas informações básicas, agora podemos dizer que o motivo pelo qual você pode ignorar a validação é porque a atribuição de restrição de tipo está removendo o
ValidateScript
fromPSVariable
object , e podemos provar que esse é o caso seguindo estas etapas:Observe que a atribuição de restrição de tipo é apenas um dos muitos métodos para remover o atributo; por exemplo, isso também funcionaria!