1

这是一个简化且完整的代码示例:

class DediInfo {
    [string]$ServiceName
    [int]$QueryPort

    DediInfo([string]$servicename, [int]$qPort){
        $this.ServiceName = $servicename
        $this.QueryPort = $qPort
    }
}

class DediInfos {
    hidden static [DediInfos] $_instance = [DediInfos]::new()
    static [DediInfos] $Instance = [DediInfos]::GetInstance()
    [System.Collections.Generic.List[DediInfo]]$Dedis = [System.Collections.Generic.List[DediInfo]]::New()

    hidden static [DediInfos] GetInstance() {
        return [DediInfos]::_instance
    }

    [void]SaveInfo(){
        $this.Dedis | Export-Clixml "D:\test.xml"
    }

    [void]LoadInfo() {
        $this.Dedis = Import-Clixml "D:\test.xml"
    }

}

$dInfos = [DediInfos]::Instance
$dInfos.Dedis.Add([DediInfo]::New("service1", 15800))
$dInfos.Dedis.Add([DediInfo]::New("service2", 15801))
$dInfos.SaveInfo()
$dInfos.Dedis = [System.Collections.Generic.List[DediInfo]]::New()
$dInfos.LoadInfo()

这是我收到的异常:

Exception setting "Dedis": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Collections.Generic.List`1[DediInfo]"."
At D:\test.ps1:25 char:9
+         $this.Dedis = Import-Clixml "D:\test.xml"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting

在过去的 4 个小时里,我一直在尝试不同的排列:

  • 添加[Serializable()]到第一堂课
  • ConvertTo-XmlList<>保存之前和从文件读取之后使用
  • 打破加载步骤以首先转储到一个新列表中 - 它确实从文件中加载数据,但我不能将它放回单例的 List<> 因为它加载为System.Object
  • 尝试使用保存到 json(如下)和相同的错误消息
    • $this.Dedis | ConvertTo-Json | Set-Content "D:\test.json"
    • $this.Dedis = Get-Content -Raw "D:\test.json" | ConvertFrom-Json
  • 还有很多其他的尝试,我已经记不起来了。

我想要的只是一种将文件保存List<>到文件然后在我的下一个脚本运行时再次加载它的方法。该示例非常简化;它保存,清除,然后尝试再次加载以显示我正在处理的内容。我读到的所有地方都是 Import-Clixml 应该将 XML 文件作为原始对象加载回,但我没有任何运气。

4

1 回答 1

2

Import-XML确实加载了对象,但不太尊重类型。在导出之前,您有一个 DediInfo 对象列表。导入后,您现在有一个Deserialized.DediInfo对象数组。

您可以通过导入并检查第一个 dediinfo 对象的基本类型来看到这一点。

$Imported = Import-Clixml "D:\test.xml"
$Imported[0].psobject.TypeNames

它会显示

Deserialized.DediInfo
Deserialized.System.Object

因此,您的转换失败,因为您试图将其转换回其原始类型,这是不可能的。

导入 XML 后,您必须再次构建 DediInfo 列表。这是对您的简单修改LoadInfo,它将起作用。

    [void]LoadInfo() {
        $this.Dedis = Foreach ($i in  Import-Clixml "D:\test.xml") {
            [DediInfo]::New($i.ServiceName, $i.QueryPort)
        }
    }
于 2021-11-14T06:03:44.793 回答