161

次の XML があるとします。

<?xml version="1.0"?>
<user_list>
   <user>
      <id>1</id>
      <name>Joe</name>
   </user>
   <user>
      <id>2</id>
      <name>John</name>
   </user>
</user_list>

そして、次のクラス:

public class User {
   [XmlElement("id")]
   public Int32 Id { get; set; }

   [XmlElement("name")]
   public String Name { get; set; }
}

XmlSerializerxmlをに逆シリアル化するために使用することは可能List<User>ですか? その場合、どのタイプの追加属性を使用する必要がありますか、またはXmlSerializerインスタンスを構築するためにどの追加パラメーターを使用する必要がありますか?

User[]少し劣る場合は、配列 ( ) を使用できます。

4

7 に答える 7

148

リストを簡単にカプセル化できます。

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

[XmlRoot("user_list")]
public class UserList
{
    public UserList() {Items = new List<User>();}
    [XmlElement("user")]
    public List<User> Items {get;set;}
}
public class User
{
    [XmlElement("id")]
    public Int32 Id { get; set; }

    [XmlElement("name")]
    public String Name { get; set; }
}

static class Program
{
    static void Main()
    {
        XmlSerializer ser= new XmlSerializer(typeof(UserList));
        UserList list = new UserList();
        list.Items.Add(new User { Id = 1, Name = "abc"});
        list.Items.Add(new User { Id = 2, Name = "def"});
        list.Items.Add(new User { Id = 3, Name = "ghi"});
        ser.Serialize(Console.Out, list);
    }
}
于 2009-03-03T21:05:23.167 に答える
54

必要な大文字と小文字を一致させるためにUserクラスを装飾する場合:XmlType

[XmlType("user")]
public class User
{
   ...
}

次に、XmlRootAttributectorXmlSerializerで目的のルートを提供し、List<> への直接読み取りを許可できます。

    // e.g. my test to create a file
    using (var writer = new FileStream("users.xml", FileMode.Create))
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<User>),  
            new XmlRootAttribute("user_list"));
        List<User> list = new List<User>();
        list.Add(new User { Id = 1, Name = "Joe" });
        list.Add(new User { Id = 2, Name = "John" });
        list.Add(new User { Id = 3, Name = "June" });
        ser.Serialize(writer, list);
    }

...

    // read file
    List<User> users;
    using (var reader = new StreamReader("users.xml"))
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(List<User>),  
            new XmlRootAttribute("user_list"));
        users = (List<User>)deserializer.Deserialize(reader);
    }

クレジット: YK1からの回答に基づく。

于 2014-02-14T11:23:51.200 に答える
16

はい、List<> をシリアライズおよびデシリアライズします。疑わしい場合は、必ず [XmlArray] 属性を使用してください。

[Serializable]
public class A
{
    [XmlArray]
    public List<string> strings;
}

これは、Serialize() と Deserialize() の両方で機能します。

于 2009-03-03T21:05:00.300 に答える
16

より良い方法を見つけたと思います。クラスに属性を入れる必要はありません。ジェネリック リストをパラメーターとして受け取るシリアライゼーションとデシリアライゼーションの 2 つのメソッドを作成しました。

見てください(私にとってはうまくいきます):

private void SerializeParams<T>(XDocument doc, List<T> paramList)
    {
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(paramList.GetType());

        System.Xml.XmlWriter writer = doc.CreateWriter();

        serializer.Serialize(writer, paramList);

        writer.Close();           
    }

private List<T> DeserializeParams<T>(XDocument doc)
    {
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(List<T>));

        System.Xml.XmlReader reader = doc.CreateReader();

        List<T> result = (List<T>)serializer.Deserialize(reader);
        reader.Close();

        return result;
    }

したがって、必要なリストをシリアル化できます。毎回リストの種類を指定する必要はありません。

        List<AssemblyBO> list = new List<AssemblyBO>();
        list.Add(new AssemblyBO());
        list.Add(new AssemblyBO() { DisplayName = "Try", Identifier = "243242" });
        XDocument doc = new XDocument();
        SerializeParams<T>(doc, list);
        List<AssemblyBO> newList = DeserializeParams<AssemblyBO>(doc);
于 2011-02-01T07:54:21.607 に答える
9

はい、List<>に逆シリアル化します。配列に保持してリストにラップ/カプセル化する必要はありません。

public class UserHolder
{
    private List<User> users = null;

    public UserHolder()
    {
    }

    [XmlElement("user")]
    public List<User> Users
    {
        get { return users; }
        set { users = value; }
    }
}

コードの逆シリアル化、

XmlSerializer xs = new XmlSerializer(typeof(UserHolder));
UserHolder uh = (UserHolder)xs.Deserialize(new StringReader(str));
于 2009-10-22T15:33:59.613 に答える
5

List<T> についてはわかりませんが、配列は確かに実行可能です。そして、ちょっとした魔法のおかげで、再びリストに簡単にアクセスできるようになります。

public class UserHolder {
   [XmlElement("list")]
   public User[] Users { get; set; }

   [XmlIgnore]
   public List<User> UserList { get { return new List<User>(Users); } }
}
于 2009-03-03T20:51:00.643 に答える
2

どうですか

XmlSerializer xs = new XmlSerializer(typeof(user[]));
using (Stream ins = File.Open(@"c:\some.xml", FileMode.Open))
foreach (user o in (user[])xs.Deserialize(ins))
   userList.Add(o);    

特に派手ではありませんが、うまくいくはずです。

于 2012-02-17T15:55:57.387 に答える