尝试在列表 <T> 上使用 Import-Clixml 时,return 值为 System.Object

When attempting to use Import-Clixml on a List<T>, the return value is System.Object

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

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 小时我一直在尝试不同的排列方式:

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

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)
        }
    }