Dot-Net

深拷貝 PSObject

  • December 8, 2021

我有一個 powershell 腳本,我在其中執行以下操作

$somePSObjectHashtables = New-Object Hashtable[] $somePSObject.Length;
$somePSObjects = Import-CSV $csvPath
0..($somePSObject.Length - 1) | ForEach-Object {
   $i = $_;
   $somePSObjectHashtables[$i] = @{};
   $somePSObject[$_].PSObject.Properties | ForEach-Object {
       $somePSObjectHashtables[$i][$_.Name] = $_.Value;
   }
}

我需要這樣做,因為我想在 CSV 中製作幾個不同的數據副本以執行幾個不同的操作。從某種意義上說,我正在對PSObject的結果數組執行“INNER JOIN” 。$somePSObjectHashtables我可以輕鬆地使用ForEach-Object迭代並在數組的每個成員上呼叫Hashtable.Clone() 。然後我可以New-Object PSObject -Property $someHashTable[$i]用來獲取 PSObject 的深層副本。

我的問題是,是否有一些更簡單的方法來製作深層副本,而無需中間雜湊表?

為了獲得真正的深度副本,我們可以使用二進制序列化(假設所有數據都是可序列化的;對於來自 CSV 的數據肯定是這種情況):

# Get original data
$data = Import-Csv ...

# Serialize and Deserialize data using BinaryFormatter
$ms = New-Object System.IO.MemoryStream
$bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$bf.Serialize($ms, $data)
$ms.Position = 0
$data2 = $bf.Deserialize($ms)
$ms.Close()

# Use deep copied data
$data2

請注意,這是一個更短,也許更簡潔的版本(我很喜歡):

$data = Import-Csv .\test.csv

$serialData = [System.Management.Automation.PSSerializer]::Serialize($data)

$data2 = [System.Management.Automation.PSSerializer]::Deserialize($serialData)

注意:然而,奇怪的是,它不保持有序雜湊表的順序。

$data = [ordered] @{
   1 = 1
   2 = 2
}

$serialData = [System.Management.Automation.PSSerializer]::Serialize($data)

$data2 = [System.Management.Automation.PSSerializer]::Deserialize($serialData)
$data2

將輸出:

Name                           Value
----                           -----
2                              2
1                              1

而對於其他類型,它工作得很好:

$data = [PsCustomObject] @{
   1 = 1
   2 = 2
}

$data = @(1, 2, 3)

引用自:https://stackoverflow.com/questions/9204829