0

Background

It started with a cmdlet as an answer for Save hash table in PowerShell object notation (PSON). Meanwhile evolved to ConvertTo-Expression. A cmdlet that serializes PowerShell objects to a PowerShell expression.
Being a little involved in the -Depth issues with similar native cmdlets (ConvertTo-Xml and ConvertTo-Json) due to recurring property references, I am wondering if this issue could be nicely resolved in a PowerShell expression.

Example

$Object = @{
    Name = "Parent"
    Child = @{
        Name = "Child"
    }
}
$Object.Child.Parent = $Object

In this example, the .Child.Parent property refers back to $Object, meaning $Object.Child.Parent.Child.Parent.Name returns Parent.
Currently, the $Object | ConvertTo-Expression returns a ScriptBlock like:

 @{
        'Child' = @{
                'Parent' = $_
                'Name' = 'Parent'
        }
        'Name' = 'Parent'
}

To reconstruct the (recurring) property reference, I might return an expression like this:

[ScriptBlock]::Create(
@'
$_ = @{
        'Child' = @{
                'Parent' = $_
                'Name' = 'Parent'
        }
        'Name' = 'Parent'
}
$_.Child.Parent = $_
$_
'@
)

(Similar to how the object is initially constructed in the example.)
Restoring (invoking, deserializing) , this expression, takes something like:

$Expression = [ScriptBlock]::Create(... # The above result
$Object = &$Expression
$Object.Child.Parent.Name

But such an output would very much muddle the result for readability.

Question

Are there any other ways (e.g. using $This, a ScriptProperty or ...) to restore a referenced property in a PowerShell object?
Is it possible to reference another property at construction time?
(I understand that the object itself is not complete, but the parent reference presumably already exists. Besides, I could imaging that the reference doesn't need to exists yet by doing some like a lazy initialization.)

iRon
  • 20,463
  • 10
  • 53
  • 79
  • That's a really complex and in-depth topic, so I don't know the answer, but just as a suggestion: may you think about re-writing your code in C# and incorporate it into a PowerShell script as dynamic type? (be aware about memory leak if added multiple times) You'll get much more capabilities this way. An example you can find at: https://blogs.technet.microsoft.com/stefan_gossner/2010/05/07/using-csharp-c-code-in-powershell-scripts/ – Max Jan 06 '19 at 01:08
  • It sounds like infinite recursion. Are you sure this construction make sense though? You probably want something similar to XML where each node has built in parent/child properties. Neither PSObject or hashtable has XML like hierarchy , so I don't think it's possible out of the box. You might build some custom tree like object type – Mike Twc Jan 06 '19 at 04:05
  • @Max, thank you for your comment. The problem is that I do not have enough C# knowledge to write something like this. I'm coming from scripting (VBScript) direction. Anyways, I have looked for the same question "*Is it possible to reference another property in a constructor?*" but could find (or understand) the answer. I guess the answer is actually **No** (For **C#**, which probably also means -but not necessarily- it is the same for **PowerShell**). If this is indeed the case, it brings to the next question: "*what is the most elegant way to (re)construct a property reference?*" – iRon Jan 06 '19 at 09:00
  • @MikeTwc, thanks for the comment. Yes, it concerns infinite recursions, but also other property references (siblings and even more distant properties) in the same object. Like and object like `$Object = get-service | Where-Object {$_.DisplayName -match 'tcp/ip*'}`, I would like to be able to transfer the references in an expression rather then creating an (infinite) list of property copies. If this can be done with an embedded custom type in the output expression and referencing properties like `[Reference]$This` and `[Reference]$This.Child`, that would be very nice. But I have no clue how. – iRon Jan 06 '19 at 12:14
  • @MikeTwc, I was not aware XML could handle references. I need to investigate this, but just just another [bug in ConvertTo-Xml](https://github.com/PowerShell/PowerShell/pull/8476#issuecomment-451736401) and in my own `ConvertTo-Expression` and an embedded `PSCustomObject` introduced since I have added a recognition for property references. :-( – iRon Jan 06 '19 at 12:19
  • 1
    Guess the short answer is 'No'. And what about child properties referencing each other? Would you cover that scenario too? Then the order in which they appear would be important etc. etc. I think there's a *reason* for the `-Depth` parameter. Anyways, you *did* mention the possibility of adding those references *after* the object was constructed. And your only reason not to do that was "it doesn't look nice". – marsze Jan 07 '19 at 08:40

0 Answers0