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

Here is a simplified and complete code example:

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

And here is the Exception I am receiving:

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

I've spent the past 4 hours trying different permutations:

What I'm wanting is just a way to save the List<> to a file and then load it back in again on my next script's run. The example is very simplified; it saves, clears, and then tries to load again to show what I'm dealing with. Everywhere I've read is that the Import-Clixml should load the XML file back in as the original object, but I'm not having any luck.

Upvotes: 1

Views: 426

Answers (1)

Sage Pourpre
Sage Pourpre

Reputation: 10333

Import-XML indeed load back the object, but does not quite respect the type. Prior export, you had a list of DediInfo objects. After import, you now have an array of Deserialized.DediInfo objects.

You can see that by doing an import and checking the base type of the first dediinfo object.

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

It will show

Deserialized.DediInfo
Deserialized.System.Object

Hence, your conversion is failing because you are trying to cast it back to its original type, which is not possible.

You will have to build your list of DediInfo again after importing the XML. Here's a simple modification to your LoadInfo that will work.

    [void]LoadInfo() {
        $this.Dedis = Foreach ($i in  Import-Clixml "D:\test.xml") {
            [DediInfo]::New($i.ServiceName, $i.QueryPort)
        }
    }

Upvotes: 2

Related Questions