【问题标题】:How can I use Import-CliXml to deserialize a generic list of custom class objects?如何使用 Import-CliXml 反序列化自定义类对象的通用列表?
【发布时间】:2016-10-25 02:22:21
【问题描述】:

我正在尝试在 PowerShell 中学习 XML 序列化。所以,我正在制作一个简单的联系人列表来序列化和反序列化。我遇到的问题是Contact 对象在我使用Import-CliXml 导入时表现不同。

这是我现在正在尝试的:

class Contact {
[string]$FirstName;
[string]$LastName;
[Int64]$PhoneNumber; }

$bob = new-object Contact
$bob.FirstName = "Bob"
$bob.LastName = "Johnson"
$bob.PhoneNumber = 1235589876

$bill = new-object Contact
$bill.FirstName = "Bill"
$bill.LastName = "Carson"
$bill.PhoneNumber = 1235589875

$ContactList = new-object System.Collections.Generic.List[Contact]
$ContactList.Add($bob)
$ContactList.Add($bill)

[xml]$data = $ContactList | convertto-xml

new-item "C:\Users\Public\Documents\Contacts.xml"
$data | export-clixml "C:\Users\Public\Documents\Contacts.xml"

[xml]$ImportedData = import-clixml "C:\Users\Public\Documents\Contacts.xml"
$ImportedList = new-object System.Collections.Generic.List[Contact]
$ImportedList = $ImportedData.Objects.Object

导入的List[Contact] 具有Contact 对象的集合,但我似乎无法从它们的属性中获取信息。例如,当我尝试以下操作时出现空行:

$ImportedList | foreach-object { write-host $_.FirstName }

我知道这些对象在那里,因为我从$ImportedList 得到了回报:

$ImportedList

Type    Property
----    --------
Contact {FirstName, LastName, PhoneNumber}
Contact {FirstName, LastName, PhoneNumber}

我正试图让它返回与 $ContactList 相同的内容:

$ContactList

FirstName LastName PhoneNumber
--------- -------- -----------
Bob       Johnson  1235589876
Bill      Carson   1235589875

任何帮助将不胜感激。

【问题讨论】:

  • 跳过ConvertTo-Xml 步骤,改为使用$ContactList |Export-CliXml

标签: xml powershell deserialization generic-list


【解决方案1】:

您遇到的问题归结为import-clixml,它不返回对象类型[contact]$ImportedData.Objects.Object 不是 [System.Xml.XmlElement] 类型,这就是你在这里得到空行的原因:

$ImportedList | foreach-object { write-host $_.FirstName }

因为管道中的对象没有属性firstname

而不是这两行:

$ImportedList = new-object System.Collections.Generic.List[Contact]
$ImportedList = $ImportedData.Objects.Object

试试这个:

$ImportedList = @()
$ImportedData.Objects.Object | %{$ImportedList += [contact]@{firstname=$_.property[0].'#text';lastname=$_.property[1].'#text';phonenumber=$_.property[2].'#text'}}

【讨论】:

  • 太棒了!我将PhoneNumber 属性转换为Int64,它就像一个魅力。谢谢!
【解决方案2】:

感谢 Tav 的明确答复。这就是我最终使用的:

$ImportedList = new-object System.Collections.Generic.List[Contact]

$ImportedData.Objects.Object | foreach-object {
$NewContact = new-object Contact
$NewContact.FirstName = $_.Property[0].'#text'
$NewContact.LastName = $_.Property[1].'#text'
$NewContact.PhoneNumber = [Int64]$_Property[2].'#text'
$ImportedList.Add($NewContact) }

更新

我能够通过Where() 方法使用属性名称:

$ImportedList = new-object System.Collections.Generic.List[Contact]

$ImportedData.Objects.Object | foreach-object {
$NewContact = new-object Contact
$NewContact.FirstName = $_.Property.Where({ $_.Name -eq "FirstName" }).'#text'
$NewContact.LastName = $_.Property.Where({ $_.Name -eq "LastName" }).'#text'
$NewContact.PhoneNumber = [Int64]$_Property.Where({ $_.Name -eq "PhoneNumber" }).'#text'
$ImportedList.Add($NewContact) }

【讨论】:

    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    相关资源
    最近更新 更多