环境信息:

PS C:\> Get-WmiObject Win32_OperatingSystem


SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 9600
RegisteredUser  : xxxxxxxxxxxxxxxxxxxxxxx
SerialNumber    : xxxxx-xxxxx-xxxxx-xxxxx
Version         : 6.3.9600 # Windows 8.1, Update 1



PS C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14409.1018
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1018
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

背景:

为什么我这样做:
  • 我的USB硬盘有点不稳定。并且我需要查找文件并逐步存储路径。
  • 如果将发生某些错误,请存储错误信息而不是路径。
  • 我打算使用[TreeElement]对象进行存储和搜索。

  • 我做了一个简单的树类:

    # need Powershell v5.0 higher
    class TreeElement
    {
        $Value = $null
        [System.Collections.Generic.List[TreeElement]] $Children = [System.Collections.Generic.List[TreeElement]]::new()
        [TreeElement] $Parent = $null
    
        TreeElement($Value)
        {
            $this.Value = $Value
        }
    
        [TreeElement] AddChild([TreeElement] $Child)
        {
            $this.Children.Add($Child)
            return $Child
        }
    
        [TreeElement] AddChildValue($ChildValue)
        {
            $Child = [TreeElement]::new($ChildValue)
            $this.Children.Add($Child)
            return $Child
        }
    }
    

    我完成了编码,并进行了如下测试:

    $root = [TreeElement]::new(1)
    $root.AddChildValue(2)
    $root.AddChildValue(3)
    $root.AddChildValue(4)
    $root.AddChildValue(5)
    
    $root
    

    最后一行将在控制台中显示此内容。

    Value Children                                             Parent
    ----- --------                                             ------
        1 {TreeElement, TreeElement, TreeElement, TreeElement}
    



    我想将$root存储到文件中。

    所以我决定使用*-Clixml,并进行编码:

    Function Store-Tree
    {
        [OutputType([void])]
        Param
        (
            [string]$Path,
            [TreeElement]$RootElement
        )
    
        Export-Clixml -Path $Path -InputObject $RootElement
    }
    
    Function Restore-Tree
    {
        Param
        (
            [string]$Path
        )
    
        # restore from xml
        $obj = Import-Clixml -Path $Path
    
        # Reconstruct instances...
        $result = Reconstruct-Tree -RootObject $obj
        return $result
    }
    
    Function Reconstruct-Tree
    {
        [OutputType([TreeElement])]
        Param
        (
            [PSObject] $RootObject
        )
    
        $root = [TreeElement]::new($RootObject.Value)
    
        foreach($ChildObject in $RootObject.Children)
        {
            [TreeElement] $branch = Reconstruct-Tree $ChildObject
            [void] $root.AddChild($branch)
        }
    
        return $root
    }
    

    然后我测试了它:

    PS> mkdir C:\temp
    PS> $path = "C:\temp\root-tree.xml"
    PS> $root # original instance
    
    Value Children                                             Parent
    ----- --------                                             ------
        1 {TreeElement, TreeElement, TreeElement, TreeElement}
    
    
    PS> Store-Tree -Path $path -RootElement $root # store in xml. instances are converted to [PsObject] internally.
    PS> $root_r = Restore-Tree -Path $path # restore instances with type of [TreeElement].
    
    Value       Children Parent
    -----       -------- ------
    TreeElement {}                      # what?
    
    

    问题:

    我期望$root_r的实例与$root几乎相同。

    但是$root_r在Children成员中具有预期的对象。

    我只想归还对象。

    调试显示,当[TreeElement]函数返回对象时,Reconstruct-Tree构造函数正在运行。

    题:

    有没有办法只返回对象?我做错什么了吗?

    我在某个网站上进行了搜索,但未获得任何信息。

    任何帮助表示赞赏。

    提前谢谢你的帮助。

    最佳答案

    自我解决。

    调试步骤1:

  • 首先粘贴代码[A]和[S]。
  • 然后用[T]测试。
  • 没什么奇怪的。

  • 调试步骤2:
  • 首先粘贴代码[A]和[S]。
  • 然后,我像[A Modifyed]一样修改了[TreeElement]类。
  • 粘贴代码[已修改]。
  • 然后,用[T]进行测试。
  • 发生了一些奇怪的事情。

  • 为什么?
  • (1)当我运行'[Amodified]'时,它将修复[TreeElement]本身的定义。
  • (2)但是函数Reconstruct-Tree中的' [TreeElement] '的定义是,不固定
  • (3)因此(1)的[TreeElement]与(2)的' [TreeElement] 是不同的类型。
  • (4)然后Reconstruct-Tree尝试返回具有旧[TreeElement]类型(' [TreeElement] ')的[TreeElment]实例。
  • (5)和powershell决定实例是' [TreeElement] 的构造函数的参数。

  • 对不起,打扰你。
    谢谢。

    样例代码:
    [A]:[TreeElement]类的定义。
    # need Powershell v5.0 higher
    class TreeElement
    {
        $Value = $null
        [System.Collections.Generic.List[TreeElement]] $Children = [System.Collections.Generic.List[TreeElement]]::new()
        [TreeElement] $Parent = $null
    
        TreeElement($Value)
        {
            $this.Value = $Value
        }
    
        [TreeElement] AddChild([TreeElement] $Child)
        {
            $this.Children.Add($Child)
            return $Child
        }
    
        [TreeElement] AddChildValue($ChildValue)
        {
            $Child = [TreeElement]::new($ChildValue)
            $this.Children.Add($Child)
            return $Child
        }
    }
    
    [修改]:[TreeElement]类的新定义。
    class TreeElement
    {
        $Value = $null
        [System.Collections.Generic.List[TreeElement]] $Children = [System.Collections.Generic.List[TreeElement]]::new()
        [TreeElement] $Parent = $null
        [string] $Dummy = "editted class type!"
    
        TreeElement($Value)
        {
            $this.Value = $Value
        }
    
        [TreeElement] AddChild([TreeElement] $Child)
        {
            $this.Children.Add($Child)
            return $Child
        }
    
        [TreeElement] AddChildValue($ChildValue)
        {
            $Child = [TreeElement]::new($ChildValue)
            $this.Children.Add($Child)
            return $Child
        }
    }
    
    [S]:存储类的实例([TreeElement])。
    Function Store-Tree
    {
        [OutputType([void])]
        Param
        (
            [string]$Path,
            [TreeElement]$RootElement
        )
    
        Export-Clixml -Path $Path -InputObject $RootElement
    }
    
    Function Restore-Tree
    {
        Param
        (
            [string]$Path
        )
    
        # restore from xml
        $obj = Import-Clixml -Path $Path
    
        # Reconstruct instances...
        $result = Reconstruct-Tree -RootObject $obj
        return $result
    }
    
    Function Reconstruct-Tree
    {
        [OutputType([TreeElement])]
        Param
        (
            [PSObject] $RootObject
        )
    
        $root = [TreeElement]::new($RootObject.Value)
    
        foreach($ChildObject in $RootObject.Children)
        {
            [TreeElement] $branch = Reconstruct-Tree $ChildObject
            [void] $root.AddChild($branch)
        }
    
        return $root
    }
    
    [T]:测试代码。
    $path = "C:\temp\root-tree.xml"
    
    $root = [TreeElement]::new(1)
    $root.AddChildValue(2)
    $root.AddChildValue(3)
    $root.AddChildValue(4)
    $root.AddChildValue(5)
    
    $root # original instance
    
    Store-Tree -Path $path -RootElement $root # store in xml. instances are converted to [PsObject] internally.
    
    $root_r = Restore-Tree -Path $path # restore instances with type of [TreeElement].
    $root_r
    

    10-04 18:35