XML Serialize可序列化对象的通用列表

Sim*_*n D 71 c# generics list xml-serialization

我是否可以序列化可序列化对象的通用列表,而无需指定其类型.

像下面破坏的代码背后的意图:

List<ISerializable> serializableList = new List<ISerializable>();

XmlSerializer xmlSerializer = new XmlSerializer(serializableList.GetType());

serializableList.Add((ISerializable)PersonList);

using (StreamWriter streamWriter = System.IO.File.CreateText(fileName))
{
    xmlSerializer.Serialize(streamWriter, serializableList);
}
Run Code Online (Sandbox Code Playgroud)

编辑:

对于那些想要了解详细信息的人:当我尝试运行此代码时,它在XMLSerializer [...]行上出错:

无法序列化System.Runtime.Serialization.ISerializable接口.

如果我改变List<object>我得到"There was an error generating the XML document.".InnerException的细节是"{"The type System.Collections.Generic.List1[[Project1.Person, ConsoleFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] may not be used in this context."}"

person对象定义如下:

[XmlRoot("Person")]
public class Person
{
    string _firstName = String.Empty;
    string _lastName = String.Empty;

    private Person()
    {
    }

    public Person(string lastName, string firstName)
    {
        _lastName = lastName;
        _firstName = firstName;
    }

    [XmlAttribute(DataType = "string", AttributeName = "LastName")]
    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    [XmlAttribute(DataType = "string", AttributeName = "FirstName")]
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

PersonList只是一个List<Person>.

这只是为了测试,所以没有觉得细节太重要了.关键是我有一个或多个不同的对象,所有这些对象都是可序列化的.我想将它们全部序列化为一个文件.我认为最简单的方法是将它们放在通用列表中并一次序列化列表.但这不起作用.

我也尝试过List<IXmlSerializable>,但是失败了

System.Xml.Serialization.IXmlSerializable cannot be serialized because it does not have a parameterless constructor.

很抱歉缺乏细节,但我是初学者,不知道需要什么细节.如果要求更多细节的人试图以一种能让我理解所需细节的方式做出回应,或者概述可能方向的基本答案,将会很有帮助.

还要感谢到目前为止我得到的两个答案 - 我可以花更多的时间阅读而不会得到这些想法.令人惊讶的是人们对这个网站的帮助.

小智 74

我有一个带有动态绑定项的通用List <>的解决方案.

class PersonalList它是根元素

[XmlRoot("PersonenListe")]
[XmlInclude(typeof(Person))] // include type class Person
public class PersonalList
{
    [XmlArray("PersonenArray")]
    [XmlArrayItem("PersonObjekt")]
    public List<Person> Persons = new List<Person>();

    [XmlElement("Listname")]
    public string Listname { get; set; }

    // Konstruktoren 
    public PersonalList() { }

    public PersonalList(string name)
    {
        this.Listname = name;
    }

    public void AddPerson(Person person)
    {
        Persons.Add(person);
    }
}
Run Code Online (Sandbox Code Playgroud)

class Person它是一个列表元素

[XmlType("Person")] // define Type
[XmlInclude(typeof(SpecialPerson)), XmlInclude(typeof(SuperPerson))]  
        // include type class SpecialPerson and class SuperPerson
public class Person
{
    [XmlAttribute("PersID", DataType = "string")]
    public string ID { get; set; }

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

    [XmlElement("City")]
    public string City { get; set; }

    [XmlElement("Age")]
    public int Age { get; set; }

    // Konstruktoren 
    public Person() { }

    public Person(string name, string city, int age, string id)
    {
        this.Name = name;
        this.City = city;
        this.Age = age;
        this.ID = id;
    }
}
Run Code Online (Sandbox Code Playgroud)

class SpecialPerson继承Person

[XmlType("SpecialPerson")] // define Type
public class SpecialPerson : Person
{
    [XmlElement("SpecialInterests")]
    public string Interests { get; set; }

    public SpecialPerson() { }

    public SpecialPerson(string name, string city, int age, string id, string interests)
    {
        this.Name = name;
        this.City = city;
        this.Age = age;
        this.ID = id;
        this.Interests = interests;
    }
}
Run Code Online (Sandbox Code Playgroud)

class SuperPerson继承Person

[XmlType("SuperPerson")] // define Type
public class SuperPerson : Person
{
    [XmlArray("Skills")]
    [XmlArrayItem("Skill")]
    public List<String> Skills { get; set; }

    [XmlElement("Alias")]
    public string Alias { get; set; }

    public SuperPerson() 
    {
        Skills = new List<String>();
    }

    public SuperPerson(string name, string city, int age, string id, string[] skills, string alias)
    {
        Skills = new List<String>();

        this.Name = name;
        this.City = city;
        this.Age = age;
        this.ID = id;
        foreach (string item in skills)
        {
            this.Skills.Add(item);   
        }
        this.Alias = alias;
    }
}
Run Code Online (Sandbox Code Playgroud)

和主要测试来源

static void Main(string[] args)
{
    PersonalList personen = new PersonalList(); 
    personen.Listname = "Friends";

    // normal person
    Person normPerson = new Person();
    normPerson.ID = "0";
    normPerson.Name = "Max Man";
    normPerson.City = "Capitol City";
    normPerson.Age = 33;

    // special person
    SpecialPerson specPerson = new SpecialPerson();
    specPerson.ID = "1";
    specPerson.Name = "Albert Einstein";
    specPerson.City = "Ulm";
    specPerson.Age = 36;
    specPerson.Interests = "Physics";

    // super person
    SuperPerson supPerson = new SuperPerson();
    supPerson.ID = "2";
    supPerson.Name = "Superman";
    supPerson.Alias = "Clark Kent";
    supPerson.City = "Metropolis";
    supPerson.Age = int.MaxValue;
    supPerson.Skills.Add("fly");
    supPerson.Skills.Add("strong");

    // Add Persons
    personen.AddPerson(normPerson);
    personen.AddPerson(specPerson);
    personen.AddPerson(supPerson);

    // Serialize 
    Type[] personTypes = { typeof(Person), typeof(SpecialPerson), typeof(SuperPerson) };
    XmlSerializer serializer = new XmlSerializer(typeof(PersonalList), personTypes); 
    FileStream fs = new FileStream("Personenliste.xml", FileMode.Create); 
    serializer.Serialize(fs, personen); 
    fs.Close(); 
    personen = null;

    // Deserialize 
    fs = new FileStream("Personenliste.xml", FileMode.Open); 
    personen = (PersonalList)serializer.Deserialize(fs); 
    serializer.Serialize(Console.Out, personen);
    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

重要的是不同类型的定义和包含.


Joh*_*ers 22

请参阅XML序列化简介:

可以序列化的项目

可以使用XmlSerializer 类序列化以下项:

  • 公共读/写属性和公共类的字段
  • 实现ICollection或的类IEnumerable
  • XmlElement 对象
  • XmlNode 对象
  • DataSet 对象

特别是,ISerializable[Serializable]属性无关紧要.


现在您已经告诉我们您的问题是什么("它不起作用"不是问题陈述),您可以获得实际问题的答案,而不是猜测.

序列化类型的集合,但实际上是序列化派生类型的实例集合时,需要让序列化程序知道您将实际序列化哪些类型.对于收藏品来说也是如此object.

您需要使用XmlSerializer(Type,Type [])构造函数来提供可能类型的列表.

  • 还要感谢有关如何提问的建议,我们对此表示赞赏. (2认同)

Tho*_*que 5

如果不指定期望的类型,则无法序列化对象集合.您必须将期望类型列表传递给XmlSerializer(extraTypes参数)的构造函数:

List<object> list = new List<object>();
list.Add(new Foo());
list.Add(new Bar());

XmlSerializer xs = new XmlSerializer(typeof(object), new Type[] {typeof(Foo), typeof(Bar)});
using (StreamWriter streamWriter = System.IO.File.CreateText(fileName))
{
    xs.Serialize(streamWriter, list);
}
Run Code Online (Sandbox Code Playgroud)

如果列表中的所有对象都继承自同一个类,则还可以使用该XmlInclude属性指定预期类型:

[XmlInclude(typeof(Foo)), XmlInclude(typeof(Bar))]
public class MyBaseClass
{
}
Run Code Online (Sandbox Code Playgroud)