c# inheriting generic collection and serialization

前端 未结 5 2077
礼貌的吻别
礼貌的吻别 2020-12-06 13:36

The setup:

class Item
{
    private int _value;

    public Item()
    {
        _value = 0;
    }

    public int Value { get { return _value; } set { _valu         


        
相关标签:
5条回答
  • 2020-12-06 13:48
    public class Animals : List<Animal>, IXmlSerializable
    {
        private static Type[] _animalTypes;//for IXmlSerializable
        public Animals()
        {
            _animalTypes = GetAnimalTypes().ToArray();//for IXmlSerializable
        }
    
        // this static make you access to the same Animals instance in any other class.
        private static Animals _animals = new Animals();
        public static Animals animals
        {
            get {return _animals; }
            set { _animals = value; }
        }
    
        #region IXmlSerializable Members
    
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
    
        public void ReadXml(System.Xml.XmlReader reader)
        {
            bool wasEmpty = reader.IsEmptyElement;
            reader.Read();
            if (wasEmpty)
                return;
    
            reader.MoveToContent();
            reader.ReadStartElement("Animals");
            // you MUST deserialize with 'List<Animal>', if Animals class has no 'List<Animal>' fields but has been derived from 'List<Animal>'.
            List<Animal> coll = GenericSerializer.Deserialize<List<Animal>>(reader, _animalTypes);
            // And then, You can set 'Animals' to 'List<Animal>'.
            _animals.AddRange(coll);
            reader.ReadEndElement();
    
            //Read Closing Element
            reader.ReadEndElement();
        }
    
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteStartElement("Animals");
            // You change 'List<Animal>' to 'Animals' at first.
            List<Animal> coll = new List<Animal>(_animals);
            // And then, You can serialize 'Animals' with 'List<Animal>'.
            GenericSerializer.Serialize<List<Animal>>(coll, writer, _animalTypes);
            writer.WriteEndElement();
        }
    
        #endregion
    
        public static List<Type> GetAnimalTypes()
        {
            List<Type> types = new List<Type>();
            Assembly asm = typeof(Animals).Assembly;
            Type tAnimal = typeof(Animal);
    
            //Query our types. We could also load any other assemblies and
            //query them for any types that inherit from Animal
            foreach (Type currType in asm.GetTypes())
            {
                if (!currType.IsAbstract
                    && !currType.IsInterface
                    && tAnimal.IsAssignableFrom(currType))
                    types.Add(currType);
            }
    
            return types;
        }
    }
    
    0 讨论(0)
  • 2020-12-06 13:49

    XmlSerializer is evil. That said, any object that implements IEnumerable will be serialized as an simple collection, ignoring any extra properties you've added yourself.

    You will need to create a new class that holds both your property and a property that returns the collection.

    0 讨论(0)
  • 2020-12-06 13:58

    I am not sure if I am missing something, but do you want the resulting xml to be

    <ItemCollection>
       <Name>name val</Name>
       <Item>
          <Value>1</alue>
       </Item
       <Item>
          <Value>2</alue>
       </Item
    </ItemCollection>
    

    If so, just apply the XmlRoot attribute to the itemcollection class and set the element name...

    [XmlRoot(ElementName="ItemCollection")]
    public class ItemCollection : Collection<Item>
    {
       [XmlElement(ElementName="Name")]
       public string Name {get;set;}
    }
    

    This will instruct the serializer to output the required name for you collection container.

    0 讨论(0)
  • 2020-12-06 14:07

    You can also try to implelemnt your own serialization using IXmlSerializable interface

        public class ItemCollection : Collection<Item>,IXmlSerializable
        {
            private string _name;
    
            public ItemCollection()
            {
                _name = string.Empty;
            }
    
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
    
     #region IXmlSerializable Members
    
             public System.Xml.Schema.XmlSchema GetSchema()
             {
                  return null;
             }
    
             public void ReadXml(System.Xml.XmlReader reader)
             {
    
             }
    
             public void WriteXml(System.Xml.XmlWriter writer)
             {
                  writer.WriteElementString("name", _name);
                  List<Item> coll = new List<Item>(this.Items);
                  XmlSerializer serializer = new XmlSerializer(coll.GetType());
                  serializer.Serialize(writer, coll);
    
             }
    
    #endregion
       }
    

    Above code will generate the serialized xml as

    <?xml version="1.0"?>
    <ItemCollection>
      <name />
      <ArrayOfItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Item>
          <Value>1</Value>
        </Item>
        <Item>
          <Value>2</Value>
        </Item>
      </ArrayOfItem>
    </ItemCollection>
    
    0 讨论(0)
  • 2020-12-06 14:09

    This behavior is "By Design". When deriving from a collection class the Xml Seralizier will only serialize the collection elements. To work around this you should create a class that encapsulates the collection and the name and have that serialized.

    class Wrapper
    {
        private Collection<Item> _items;
        private string _name;
    
        public Collection<Item> Items { get {return _items; } set { _items = value; } }
        public string Name { get { return _name; } set { _name = value; } }
    }
    

    A detailed discussion is available here: http://blogs.vertigo.com/personal/chris/Blog/archive/2008/02/01/xml-serializing-a-derived-collection.aspx

    0 讨论(0)
提交回复
热议问题