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

Time:11-14

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:

  • adding [Serializable()] to the first class
  • using the ConvertTo-Xml on the List<> before saving and after reading from file
  • breaking out the load steps to dump into a new list first - which does load the data from file, but I can't put it back to the singleton's List<> because it loads as System.Object
  • Tried using saving to json (below) and same error message
    • $this.Dedis | ConvertTo-Json | Set-Content "D:\test.json"
    • $this.Dedis = Get-Content -Raw "D:\test.json" | ConvertFrom-Json
  • Lots of other attempts that I cannot remember any longer.

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.

CodePudding user response:

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