Reputation: 193
I have an object that has an array of objects as a property.
PS C:\> $Object
GroupType : Object
StateRevCounter : 3846
SchemaTag : Computer
PropGroupList : {DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup...}
PS C:\> $Object.PropGroupList
Tag PropertyList
--- ------------
BasicInventory {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfString, DSM.MdsTypedPr...
ClientInfo {DSM.MdsTypedPropertyOfNullableOfDateTime, DSM.MdsTypedPropertyOfNullableOf...
Computer {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfNullableOfDateTime, DS...
CustomPatchManagement {DSM.MdsTypedPropertyOfNullableOfBoolean, DSM.MdsTypedPropertyOfString}
HardwareBasedRemoteMgmt {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfNullableOfBoolean, DSM...
PS C:\> $Object.PropGroupList.PropertyList
TypedValue Tag Type
---------- --- ----
7.4.1.4461 ClientVersion String
Client ComputerRole Option
169 CPUArchitecture CatalogLink
2262 CPUType CatalogLink
DSMCLIENT00.Computers.ideri.dev DirectoryContext String
DSMClient00.ideri.dev FullQualifiedName String
InfrastructureRole Option
000C29E1B2FD InitialMACAddress String
227 InstalledOS CatalogLink
315 InstalledOSCulture CatalogLink
1458 InstalledOSFlavor CatalogLink
Windows 10 Enterprise 1511 InstalledOSFriendlyName String
DSM.MdsVersion InstalledOSVersion Version
4193 InstalledRAM Int32
66057 LastBootServer Int32
.....
Now I want to create AliasProperties for $Object to show the values of $Object.PropGroupList.PropertyList
directly within the output of $Object and update the values at the right spot, if the AliasProperty is changed.
Desired output:
PS C:\> $Object
BasicInventory_ClientVersion : 7.4.1.4461
BasicInventory_ComputerRole : Client
BasicInventory_CPUArchitecture : 169
...
GroupType : Object
StateRevCounter : 3846
SchemaTag : Computer
PropGroupList : {DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup...}
So if I then update BasicInventory_ClientVersion to for example 10.4.2.3333, the corresponding value in the sub property (array) is updated as well and vice versa.
Is this even possible with Add-Member -MemberType AliasProperty
? Or can I only add AliasProperties for properties in the root of the object?
Regards Sebbo
Upvotes: 0
Views: 668
Reputation: 193
As @AdminOfThings suggested, I used ScriptProperty in the end. Thanks. I've ended up building a function to add the properties with the right links to the array.
As you can see, I had to compose the script block as a string first to get the values of my variables resolved first. If I would have written it in the script block directly, the variable $prop.Tag
for example would not have been resolved, as it is not set in the script block.
function ExpandObjectMdsPropGroupList ($ObjectList)
{
foreach($obj in $ObjectList)
{
$PropGroupList = $obj.Propgrouplist
foreach($propGrp in $PropGroupList)
{
foreach($prop in $propGrp.PropertyList)
{
# compose the getter
$GetterScriptBlockAsString = "(`$this.propGroupList.PropertyList | Where-Object{`$_.Tag -eq `"$($prop.Tag)`"}).TypedValue"
$GetterScriptBlock = [scriptblock]::Create($GetterScriptBlockAsString)
# compose the setter
[string]$typeOfPropTypedValue = $null
try{
# get the type of TypedValue
$typeOfPropTypedValue = $prop.TypedValue.GetType()
}catch{
# If TypedValue is null we have to get the type from get-member
$memberType = ($prop | Get-Member -Name TypedValue).Definition
$typeOfPropTypedValue = ($memberType.Remove($memberType.IndexOf(' ')))
}
if($typeOfPropTypedValue){
$typeOfPropTypedValue = "[$typeOfPropTypedValue]"
}
$SetterScriptBlockAsString = "param($typeOfPropTypedValue`$val);(`$this.propGroupList.PropertyList | Where-Object{`$_.Tag -eq `"$($prop.Tag)`"}).TypedValue = `$val"
$SetterScriptBlock = [scriptblock]::Create($SetterScriptBlockAsString)
# Add the member to the object
$obj | Add-Member -MemberType ScriptProperty -Name "$($propGrp.Tag)_$($prop.Tag)" -Value $GetterScriptBlock -SecondValue $SetterScriptBlock
}
}
}
$ObjectList
}
Now I can use the function on any object with PropGroupList as a property and it adds the ScriptProperties no mather what PropGroups are in the List.
Thanks to the getters and setters I can update the values on either side.
Regards Sebbo
Upvotes: 1
Reputation: 25001
You can use a Add-Member
to add member type ScriptProperty
. However, building the object is a fairly manual process. Here is an example using two properties, ClientVersion
and ComputerRole
.
$object | Add-Member -MemberType ScriptProperty -Name "BasicInventory_ClientVersion" -Value {
(($this.propgrouplist | Where Tag -eq 'BasicInventory').propertylist | where Tag -eq 'ClientVersion').TypedValue
}
$object | Add-Member -MemberType ScriptProperty -Name "BasicInventory_ComputerRole" -Value {
(($this.propgrouplist | Where Tag -eq 'BasicInventory').propertylist | where Tag -eq 'ComputerRole').TypedValue
}
Now you can update the source property and have it be reflected in the scriptproperty.
# Properties Before Change
$object | fl
GroupType : Object
PropGroupList : @{Tag=BasicInventory; PropertyList=System.Object[]}
BasicInventory_ClientVersion : 7.4.1.4461
BasicInventory_ComputerRole : Client
# Properties After Change
($Object.PropGroupList.PropertyList | Where Tag -eq 'ClientVersion').TypedValue = '20.3.4'
$object | fl
GroupType : Object
PropGroupList : @{Tag=BasicInventory; PropertyList=System.Object[]}
BasicInventory_ClientVersion : 20.3.4
BasicInventory_ComputerRole : Client
Use caution when trying to make this dynamic with variables. Any variable used in the scriptproperty value will be computed when the object is called based on the variables defined in the calling scope. For example, if you assigned value to be {$tag}
, $tag
would need to be defined somewhere before $object
is retrieved.
Upvotes: 1