How can one change the property value of an object in Powershell which is not at the first layer?
Let's take this object
$MyObject = [PSCustomObject]@{
Name = 'test'
SomeComplexObject = @{
Prop1 = 'AAA'
Prob2 = 'BBB'
}
}
Should I need to change a surface property (first layer), I can simply do:
# The Idea is that I don't know what is the property name because I get it dynamically.
$ThePropertyNameIWantToChange = "Name"
$MyObject.$ThePropertyNameIWantToChange = "New Value"
How can I do the same if I need to change Prop1
?
# This won't work obvisouly but this is to show the gist of it.
$SubProperty = "SomeComplexObject.Prop1"
$MyObject.$SubProperty = "New Value"
The idea is that whenever I change a property value, there is stuff (same stuff always) that need to be performed before and after.
I would like to be able to do something like this.
ChangeObjectValue -InputObject $MyObject -Parameter {$_.SomeComplexObject} -Value 'New Value'
So far, I was able to do this by:
- Converting the scriptblock to a string, then doing some replace / append, creating a new scriptblock, and invoking it.
I came up with the following (working)
$MyObject = [PSCustomObject]@{
Name = 'test'
SomeComplexObject = @{
Prop1 = 'AAA'
Prob2 = 'BBB'
}
}
function ChangeObjectValue {
param (
[Object]$ConfigObject,
[ScriptBlock]$ScriptBlock,
[Object]$Value
)
$NewSblockStr = $ScriptBlock.ToString().Replace('$_.', '$args[0].') + '= $args[1]'
$NewSb = [scriptblock]::Create($NewSblockStr)
Write-Host 'Do stuff I need before' -ForegroundColor Green
$NewSb.Invoke($ConfigObject, $Value)
Write-Host 'Done' -ForegroundColor Cyan
}
Write-Host $MyObject.SomeComplexObject.Prop1 -ForegroundColor Cyan
ChangePPValue -ConfigObject $MyObject -ScriptBlock { $_.SomeComplexObject.Prop1 } -Value 'JAREF'
$MyObject.SomeComplexObject.Prop1
That being said, it feels a bit finicky and I was wondering if there was a more robust way to achieve this without what seems to me to be the long way around.
Summary We all know we can assign a value to an object dynamically by using a string as the property name (which can come from a variable or be passed down from a function) but what about drilling down into an object to set a second or third level property? Is there a simple way to do this?