How to create new clone instance of PSObject object

前端 未结 9 685
野趣味
野趣味 2020-12-09 02:20

I want to create new instance of my custom PSObject. I have a Button object created as PSObject and I want to create new object Button2 which has the same members as Button

9条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-09 03:20

    Based on the answer by @TeraFlux, here's a function that will do a deep copy on multiple objects and accepts pipeline input.

    Note, it leverages json conversion with a default depth of 100, which lends it to a few weaknesses

    • It's going to be slow on deep or complex objects, or objects with expensive (slow) pseudoproperties (methods pretending to be properties that are calculated on the fly when asked for)
      • Though it should still be faster than the Add-Member approach because the heavy lifting is going through a compiled function
    • Anything that can't be stored in JSON may get corrupted or left behind (methods will be a prime candidate for this type of error)
      • Though any object that can safely go through this process should be savable, able to be safely stored (for recovery) or exported for transportation

    I would be interested in any caveats or improvements to deal with these

    function Clone-Object 
        {
        [CmdletBinding()]
        Param `
            (
            [Parameter(ValueFromPipeline)] [object[]]$objects,
            [Parameter()] [int] $depth = 100
            )
        $clones = foreach
            ($object in $objects)
            {
            $object | ConvertTo-Json -Compress -depth $depth | ConvertFrom-Json
            }
        return $clones
        }
    

    Here are some very basic unit tests

    $testClone = `
        {
        $test1 = $null
        $test2 = $null
        $test3 = $null
    
        $Test1 = [psCustomObject]@{a=1; b=2; c=3; d=4}
        $Test2 = $Test1 | ConvertTo-Json -depth 100 | ConvertFrom-Json
        $Test2 | add-Member -Name "e" -Value "5" -MemberType noteproperty
        $Test3 = $test2 | Clone-Object
        $Test3 | add-Member -Name "f" -Value "6" -MemberType noteproperty
        $Test1.a = 7
        $Test2.a = 8
    
        #$Expected0 = [psCustomObject]@{a=1; b=2; c=3; d=4}
        $Expected1 = [pscustomobject]@{a=7; b=2; c=3; d=4}
        $Expected2 = [pscustomobject]@{a=8; b=2; c=3; d=4; e=5}
        $Expected3 = [pscustomobject]@{a=1; b=2; c=3; d=4; e=5; f=6}
    
        $results1 = @(); $results1+=$test1; $results1+=$expected1
        $results2 = @(); $results2+=$test2; $results2+=$expected2
        $results3 = @(); $results3+=$test3; $results3+=$expected3
        $results1 | Format-Table # if these don't match then its probably passing references (copy not clone)
        $results2 | Format-Table # if these don't match the core approach is incorrect
        $results3 | Format-Table # if these don't match the function didn't work
    
        }
    &$testClone
    

提交回复
热议问题