Глубокое копирование PSObject

У меня есть скрипт 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, чтобы выполнить несколько различных манипуляций. В некотором смысле я выполняю "INNER JOIN" в результирующем массиве PSObject. Я могу легко перебрать $somePSObjectHashtables с ForEach-Object и вызовите Hashtable.Clone() для каждого члена массива. Я могу тогда использовать New-Object PSObject -Property $someHashTable[$i] чтобы получить глубокую копию PSObject.

У меня вопрос, есть ли какой-нибудь более простой способ сделать глубокую копию без посредника Hashtable?

1 ответ

Решение

Для получения действительно глубоких копий мы можем использовать двоичную сериализацию (при условии, что все данные сериализуемы; это определенно относится к данным, полученным из 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)

Вот еще более короткий, который я использую как функцию:

using namespace System.Management.Automation
function Clone-Object ($InputObject) {
    <#
    .SYNOPSIS
    Use the serializer to create an independent copy of an object, useful when using an object as a template
    #>
    [psserializer]::Deserialize(
        [psserializer]::Serialize(
            $InputObject
        )
    )
}
Другие вопросы по тегам