【问题标题】:When attempting to use Import-Clixml on a List<T>, the return value is System.Object尝试在 List<T> 上使用 Import-Clixml 时,返回值为 System.Object
【发布时间】:2021-12-25 20:04:12
【问题描述】:

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

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()]
  • 在保存之前和从文件读取之后在List&lt;&gt; 上使用ConvertTo-Xml
  • 首先打破加载步骤转储到一个新列表中 - 它确实从文件加载数据,但我不能将它放回单例列表,因为它加载为System.Object
  • 尝试使用保存到 json(如下)和相同的错误消息
    • $this.Dedis | ConvertTo-Json | Set-Content "D:\test.json"
    • $this.Dedis = Get-Content -Raw "D:\test.json" | ConvertFrom-Json
  • 许多其他的尝试,我已经记不得了。

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

【问题讨论】:

    标签: powershell powershell-5.1


    【解决方案1】:

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

    【讨论】:

    • 这是我在发布后最终做的事情。我有点希望我不必为加载的每个字段指定 .property 名称。
    • @вʀaᴎᴅᴏƞвєнᴎєƞ 从技术上讲,您可以,根据您的需要,这可能就足够了。如果您将$Dedis 的类型从转换对象列表 (DediInfo) 更改为通用对象,例如 ` [System.Collections.Generic.List[Object]]$Dedis = [System.Collections.Generic.List [对象]]::New()`。这样,'DediInfo' 和 'Deserialized.DediInfo' 都可以工作。如果没有尝试将对象类型转换回 DediInfo,那么所有属性/方法都会很好。
    • 我宁愿拥有强类型的属性名称,而不是将其保留为通用对象。加载方法和类描述符保存在同一个文件中;我只是在文件顶部和 load 方法上方写了一个 BIG COMMENT 来提醒我,如果我进行任何更改,我需要在 load 方法中指定所有属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 1970-01-01
    • 2017-11-01
    • 2018-08-23
    • 2012-08-28
    • 2010-12-26
    • 1970-01-01
    相关资源
    最近更新 更多