【问题标题】:Add-Member AliasProperty to sub property in PowerShell将成员 AliasProperty 添加到 PowerShell 中的子属性
【发布时间】:2020-06-25 14:08:33
【问题描述】:

我有一个对象,它有一个对象数组作为属性。

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
.....

现在我想为 $Object 创建 AliasProperties 以直接在 $Object 的输出中显示 $Object.PropGroupList.PropertyList 的值,如果 AliasProperty 发生更改,则在正确的位置更新值。

期望的输出:

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...}

因此,如果我随后将 BasicInventory_ClientVersion 更新为例如 10.4.2.3333,则子属性(数组)中的相应值也会更新,反之亦然。

Add-Member -MemberType AliasProperty 甚至可以做到这一点吗?还是只能在对象的根目录中为属性添加 AliasProperties?

问候 赛博

【问题讨论】:

  • 我会为此使用ScriptProperty

标签: arrays powershell properties add member


【解决方案1】:

您可以使用Add-Member 添加成员类型ScriptProperty。但是,构建对象是一个相当手动的过程。这是一个使用两个属性的示例,ClientVersionComputerRole

$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
}

现在您可以更新源属性并将其反映在脚本属性中。

# 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

尝试使用变量进行动态化时要小心。在调用对象时,将根据调用范围中定义的变量计算脚本属性值中使用的任何变量。例如,如果您将值指定为 {$tag},则需要在某处定义 $tag,然后才能检索到 $object

【讨论】:

    【解决方案2】:

    正如@AdminOfThings 建议的那样,我最终使用了 ScriptProperty。谢谢。 我最终构建了一个函数来添加具有正确链接的属性到数组。

    如您所见,我必须首先将脚本块组合为字符串,才能首先解析变量的值。如果我直接在脚本块中编写它,变量$prop.Tagfor example 将不会被解析,因为它没有在脚本块中设置。

    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
    }
    

    现在我可以在任何将 PropGroupList 作为属性的对象上使用该函数,并且它添加了 ScriptProperties 而不是 List 中的 PropGroups。

    感谢 getter 和 setter,我可以更新任一侧的值。

    问候 赛博

    【讨论】:

      猜你喜欢
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多