I've got a hashtable with variables. The source of this hashtable is an empty parameters.json (for deployment of Azure resources) converted to a hashtable.
For this question I have simplified this hashtable to the following:
$deploymentParameters = [PSCustomObject]@{
key1 = $null
key2 = $null
key3 = $null
}
During the execution of my script some of these variables will be filled from within my script (like generated objectnames), but others (like a region) will depend on user input.
I have defined all user input in a seperate definition. In this definition I include the name, userprompt and the type of the variable. The simplified definition looks like this:
$userInput = @(
[PSCustomObject]@{
Name = "key1"
UserPrompt = "Please enter the value for key1"
Type = [String]
},
[PSCustomObject]@{
Name = "key2"
UserPrompt = "Please enter the value for key2"
Type = [String]
},
[PSCustomObject]@{
Name = "key3"
UserPrompt = "Please enter the value for key3"
Type = [Int]
}
)
In my script I can combine these with the following codeblock:
foreach ($parameter in $userInput)
{
$value = Read-Host "Please enter the value for '$($parameter.UserPrompt)'"
$deploymentParameters.$($parameter.Name) = $value
}
This works, yet $deploymentParameters.key3.GetType()
will show this value is a string instead of an integer.
I tried casting the value to it's correct type with the following code:
foreach ($parameter in $userInput)
{
$value = Read-Host "Please enter the value for '$($parameter.UserPrompt)'"
[$parameter.Type] $deploymentParameters.$($parameter.Name) = $value
}
This will throw an error Missing type name after '['
I have been able to get this to work using a switch-case:
foreach ($parameter in $userInput)
{
$value = Read-Host "Please enter the value for '$($parameter.UserPrompt)'"
switch ($parameter.Type.Name)
{
"Int32"
{
[Int] $deploymentParameters.$($parameter.Name) = $value
}
"String"
{
[String] $deploymentParameters.$($parameter.Name) = $value
}
default
{
$null
}
}
}
This solution isn't really maintainable though since I would have to include all cases I could encounter (or default anything not caught to a string).
Is there any way to actually cast to a specific type based on a parameter value?
Easiest way to cast them is using the -as
operator, however you should note that when coercion fails, -as
returns a null
value.
foreach ($parameter in $userInput) {
$value = Read-Host "Please enter the value for '$($parameter.UserPrompt)'"
$deploymentParameters.$($parameter.Name) = $value -as $parameter.Type
}
If instead you want to get an error when coercion failed, you can use LanguagePrimitives.ConvertTo
:
foreach ($parameter in $userInput) {
$value = Read-Host "Please enter the value for '$($parameter.UserPrompt)'"
$deploymentParameters.$($parameter.Name) = [System.Management.Automation.LanguagePrimitives]::ConvertTo(
$value, $parameter.Type)
}