1

我的目标是创建一个自定义数据对象,它有两个离散变量(fooNamefooUrl)和一个列表fooChildren,每个列表项都有两个离散变量变量childAgechildName

目前,我有这个:

$fooCollection = [PSCustomObject] @{fooName=""; fooUrl=""; fooChildrenList=@()} 

$fooCollection.fooName = "foo-a-rama"
$fooCollection.fooUrl = "https://1.2.3.4"

$fooChild = New-Object -TypeName PSobject
$fooChild | Add-Member -Name childAge -MemberType NoteProperty -Value 6
$fooChild | Add-Member -Name childName -MemberType NoteProperty -Value "Betsy"
$fooCollection.fooChildrenList += $fooChild

$fooChild = New-Object -TypeName PSobject
$fooChild | Add-Member -Name childAge -MemberType NoteProperty -Value 10
$fooChild | Add-Member -Name childName -MemberType NoteProperty -Value "Rolf"
$fooCollection.fooChildrenList += $fooChild

cls
$fooCollection.fooName
$fooCollection.fooUrl

foreach ($fooChild in $fooCollection.fooChildrenList)
{
    ("  " + $fooChild.childName + " " + $fooChild.childAge)
}

这会产生以下内容。到现在为止还挺好

foo-a-rama
https://1.2.3.4
  Betsy 6
  Rolf 10

问题:我不喜欢使用+=,因为据我了解,每次执行都会+=导致创建副本(无论处于何种状态) 。$fooCollection.fooChildrenList+=

因此,我不想实现as ,而是实现fooChildrenListas ,以便可以根据需要添加每一行。我已经尝试了各种在代码中执行此操作的方法,但最终无人居住。例如:@()fooChildrenListNew-Object System.Collections.ArrayListfooChildrenList

$fooCollection = [PSCustomObject] @{fooName=""; fooUrl=""; fooChildrenList = New-Object System.Collections.ArrayList} 

$fooCollection.fooName = "foo-a-rama"
$fooCollection.fooUrl = "https://1.2.3.4"

$fooChild.childName = "Betsy"
$fooChild.childAge = 6
$fooCollection.fooChildrenList.Add((New-Object PSObject -Property $fooChild))

$fooChild.childName = "Rolf"
$fooChild.childAge = 10
$fooCollection.fooChildrenList.Add((New-Object PSObject -Property $fooChild))

$fooCollection | get-member节目

TypeName: System.Management.Automation.PSCustomObject

Name            MemberType   Definition                                   
----            ----------   ----------                                   
Equals          Method       bool Equals(System.Object obj)               
GetHashCode     Method       int GetHashCode()                            
GetType         Method       type GetType()                               
ToString        Method       string ToString()                            
fooChildrenList NoteProperty System.Collections.ArrayList fooChildrenList=
fooName         NoteProperty string fooName=foo-a-rama                    
fooUrl          NoteProperty string fooUrl=https://1.2.3.4  

$fooCollection节目

fooName         : foo-a-rama
fooUrl          : https://1.2.3.4
fooChildrenList : {} 

如何将 System.Collections.ArrayList 添加到 PowerShell 自定义对象?

4

3 回答 3

2

好吧,我不确定你遇到了什么问题,它对我来说很好用

function New-Child([string]$Name, [int]$Age){
    $Child = New-Object -TypeName PSobject
    $Child | Add-Member -Name childAge -MemberType NoteProperty -Value $age -PassThru | 
    Add-Member -Name childName -MemberType NoteProperty -Value $name
    return $child
}

$fooCollection = [PSCustomObject] @{fooName=""; fooUrl=""; fooChildrenList = New-Object System.Collections.ArrayList} 

$fooCollection.fooName = "foo-a-rama"
$fooCollection.fooUrl = "https://1.2.3.4"
$fooCollection.fooChildrenList.Add((New-Child -Name "Betty" -Age 9)) | Out-Null
$fooCollection.fooChildrenList.Add((New-Child -Name "Ralf" -Age 15)) | Out-Null

$fooCollection.fooName
$fooCollection.fooUrl
foreach ($fooChild in $fooCollection.fooChildrenList)
{
    "  " + $fooChild.childName + " " + $fooChild.childAge
}

输出

foo-a-rama
https://1.2.3.4
  Betty 9
  Ralf 15
于 2018-09-14T17:31:37.337 回答
2

挑战是每次添加到列表时都添加$fooChild [pscustomobject]重复使用实例副本.Add()(如果不使用副本,最终将得到所有列表元素都指向同一个对象)。

但是,您不能使用 克隆现有[pscustomobject](又名[psobject])实例New-Object PSObject -Property

一种选择(PSv3+)是将可重用对象定义$fooChild有序哈希表,然后使用[pscustomobject] cast,它每次都会隐式创建一个新对象:

$fooCollection = [PSCustomObject] @{ fooChildrenList = New-Object Collections.ArrayList } 

# Create the reusable $fooChild as an *ordered hashtable* (PSv3+)
$fooChild = [ordered] @{ childName = ''; childAge = -1 }

# Create 1st child and add to list with [pscustomobject] cast
$fooChild.childName = 'Betsy'; $fooChild.childAge = 6
$null = $fooCollection.fooChildrenList.Add([pscustomobject] $fooChild)

# Create and add another child.
$fooChild.childName = 'Rolf'; $fooChild.childAge = 10
$null = $fooCollection.fooChildrenList.Add([pscustomobject] $fooChild)

# Output the children
$fooCollection.fooChildrenList

请注意,它会抑制方法调用$null = ...中通常不需要的输出。.Add()

以上产生:

childName childAge
--------- --------
Betsy            6
Rolf            10

一个稍微模糊的替代方法是坚持$fooChild作为一个[pscustomobject]实例并调用.psobject.Copy()它来创建一个克隆。


ArcSet 的有用答案提供了一个更加模块化的解决方案,它通过帮助函数按需创建新的自定义对象实例


最后,在PSv5+中,您可以定义一个辅助

$fooCollection = [PSCustomObject] @{ fooChildrenList = New-Object Collections.ArrayList } 

# Define helper class
class FooChild {
  [string] $childName
  [int]    $childAge
}

# Create 1st child and add to list with [pscustomobject] cast
$null = $fooCollection.fooChildrenList.Add([FooChild] @{ childName = 'Betsy'; childAge = 6 })

# Create and add another child.
$null = $fooCollection.fooChildrenList.Add([FooChild] @{ childName = 'Rolf'; childAge = 10 })

# Output the children
$fooCollection.fooChildrenList

[FooChild]请注意如何通过简单地转换具有与类属性名称匹配的条目的哈希表来创建实例。

于 2018-09-14T17:43:22.007 回答
0

从我用来制作一些阵列的东西中快速复制粘贴。我必须创建自定义对象,然后将它们添加到数组中。它需要针对您的场景进行修改,但我认为它会为您提供所需的东西。

[System.Collections.ArrayList]$SQL_Query_Results = @()

ForEach ($SQL_Index in $SQL_Table) {

    $SQL_Array_Object = [PSCustomObject]@{
        'Computer_Name'    = $SQL_Table[$SQL_Index_Counter].ComputerID -replace ",", ""
        'Project'          = $SQL_Table[$SQL_Index_Counter].Project
        'Site'             = $SQL_Table[$SQL_Index_Counter].Site
        'Description'      = $SQL_Table[$SQL_Index_Counter].Description -replace ",", ""
        'Physical_Machine' = $SQL_Table[$SQL_Index_Counter].IsPhysicalMachine
        'Active'           = $SQL_Table[$SQL_Index_Counter].IsActive
    }

    $SQL_Query_Results.Add($SQL_Array_Object) | Out-Null
}

编辑以显示最初如何创建 Array。

于 2018-09-14T17:03:51.767 回答