Question

I have a powershell script in which I do the following

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

I need to do this because I want to make several distinct copies of the data in the CSV to perform several distinct manipulations. In a sense I'm performing an "INNER JOIN" on the resulting array of PSObject. I can easily iterate through $somePSObjectHashtables with a ForEach-Object and call Hashtable.Clone() on each member of the array. I can then use New-Object PSObject -Property $someHashTable[$i] to get a deep copy of the PSObject.

My question is, is there some easier way of making the deep copy, without an intermediary Hashtable?

Was it helpful?

Solution

For getting really deep copies we can use binary serialization (assuming that all data are serializable; this is definitely the case for data that come from 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

OTHER TIPS

Note that here is a shorter, maybe a bit cleaner version of this (that I quite enjoy):

$data = Import-Csv .\test.csv

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

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

Here's an even shorter one that I use as a function:

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
        )
    )
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top