如何序列化我自己的通用列表?

时间:2018-01-09 09:54:03

标签: c# xml list serialization

我写了一个通用的List类型。如何使List可序列化?我主要关心的是GetObjectData()方法。

以下是我的List类及其方法。我之前使用C#中已有的List<>进行了XML序列化,但我不知道应该在GetObjectData()方法中写什么。某种形式的foreach循环可能?

class Liste<T> : IEnumerable, ISerializable
{
    List_Element<T> First;
    List_Element<T> Last;
    int position = -1;
    public T this[int index]
    {
        get
        {
            return GetAt(index);
        }
        set
        {
            //Person p = new Person();
            //InsertAt(index, p);
        }
    }
    public bool MoveNext()
    {
        position++;
        if (currentElement == null)
        {
            currentElement = First;
        }
        else
        {
            currentElement = currentElement.Next;
        }
        return (position < Count);
    }
    internal bool MovePrev()
    {
        position--;
        if (currentElement == null)
        {
            currentElement = Last;
        }
        else
        {
            currentElement = currentElement.Prev;
        }
        return currentElement != null;
    }
    private List_Element<T> currentElement;
    public T Current
    {
        get
        {
            return currentElement.Data;
        }
    }
    public void Add(T data)
    {
        List_Element<T> listelement = new List_Element<T>();
        listelement.Data = data;
        if (First == null)
        {
            First = listelement;
            Last = listelement;
        }
        else
        {
            Last.Next = listelement;
            listelement.Prev = Last;
            Last = listelement;
        }
        Count++;
    }
    public int Count { get; private set; }
    public void NeueListe()
    {
        First = null;
    }
    public void InsertEnd(T data)
    {
        List_Element<T> ende = new List_Element<T>();
        ende.Data = data;
        if (First == null)
        {
            First = ende;
            Last = ende;
        }
        else
        {
            Last.Next = ende;
            ende.Prev = Last.Prev;
            Last = ende;
            ende.Prev.Prev = Last.Prev.Prev;
        }
        Count++;
    }
    public void Reset()
    {
        position = -1;
    }
    public T GetAt(int index)
    {
        List_Element<T> laufvariable;
        laufvariable = First;
        for (int i = 0; i < index; i++)
        {
            laufvariable = laufvariable.Next;
        }
        if (index == 0)
        {
            return laufvariable.Data;
        }
        else
        {
            return laufvariable.Data;
        }
    }
    public void InsertAt(int index, T data)
    {
        List_Element<T> insertElement = new List_Element<T>();
        insertElement.Data = data;
        if (index == 0)
        {
            insertElement.Next = First;
            First = insertElement;
        }
        else
        {
            List_Element<T> laufVariable;
            laufVariable = First;
            for (int i = 0; i < index - 1; i++)
            {
                laufVariable = laufVariable.Next;
            }
            insertElement.Next = laufVariable.Next;
            laufVariable.Next = insertElement;
            insertElement.Prev = laufVariable;
        }
        if (insertElement.Next == null)
        {
            Last = insertElement;
        }
        else
        {
            insertElement.Next.Prev = insertElement;
        }
    }
    public void RemoveAt(int index)
    {
        if (index == 0)
        {
            if (Count == 1)
            {
                First = null;
                Last = null;
                Count--;
                return;
            }
            //First = First.Next;
            //First.Prev = null;
            else
            {
                First = First.Next;
                First.Prev = null;
                Count--;
            }
        }
        else
        {
            List_Element<T> laufvariable;

            laufvariable = First;
            for (int i = 0; i < index - 1; i++)
            {
                laufvariable = laufvariable.Next;
            }
            if (laufvariable.Next.Next == null)
            {
                Last = laufvariable;
                laufvariable.Next = null;
            }
            else
            {
                laufvariable.Next = laufvariable.Next.Next;
                laufvariable.Next.Prev = laufvariable;
            }
            Count--;
        }
    }
    public void Removelast(int index)
    {
        List_Element<T> laufvariable;
        laufvariable = First;
        for (int i = 0; i < index - 1; i++)
        {
            laufvariable = laufvariable.Next;
        }
        laufvariable = null;
    }
    public IEnumerator GetEnumerator()
    {
        if (First == null)
        {
            yield break;
        }

        if (First == Last)
        {                
            yield return First;
            MoveNext();
        }

        MoveNext();

        while (currentElement != null)
        {           
            yield return currentElement;
            MoveNext();
        }

        if (currentElement == null)
        {
            Reset();
            yield break;
        }

    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // What to do here?
    }

1 个答案:

答案 0 :(得分:0)

稍微修改一下你的问题,你在问:

  

我有一个实现IEnumerable的自定义通用集合。如何在.Net中将其序列化为XML?

.Net有两个XML序列化程序,XmlSerializerDataContractSerializer。两者都有序列化集合的特殊规则,这些集合记录在以下位置:

尽管这些序列化程序不共享代码库,但它们的规则非常相似:

  1. 该类型应实现IEnumerable<T>以及IEnumerable,以便序列化程序可以确定预期的元素类型。

  2. 该类型必须具有无参数构造函数。

  3. 该类型必须具有公共Add(T item)方法,其单个参数可从通用枚举器的泛型类型T分配。

  4. 对于多种类型IEnumerable<T>,该类型无法多次实施T

  5. 仅限
  6. XmlSerializer类型(和通用项目类型)必须是公开的。

  7. 集合项目已序列化而不是集合属性XmlSerializer永远不会序列化集合属性。 DataContractSerializer仅在集合标有[DataContract]时序列化集合属性,在这种情况下,属性是序列化而不是项目,而不是项目。

  8. 通过遵循这些规则,您可以避免完全实现IXmlSerializable,这很棘手,容易出现细微的错误。

    因此,如果我大大简化Liste<T>,则两个序列化程序都可以序列化以下实现:

    public class Liste<T> : IEnumerable<T>
    {
        readonly List<T> underlyingList = new List<T>();
    
        public void Add(T item)
        {
            underlyingList.Add(item);
        }
    
        #region IEnumerable<T> Members
    
        public IEnumerator<T> GetEnumerator()
        {
            return underlyingList.GetEnumerator();
        }
    
        #endregion
    
        #region IEnumerable Members
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
        #endregion
    }
    

    如果我按如下方式定义List<int>

    var list = new Liste<int>
    {
        1, 2, 3, 4,
    };
    

    两个序列化程序都将生成以下XML:

    <ArrayOfInt>
      <int>1</int>
      <int>2</int>
      <int>3</int>
      <int>4</int>
    </ArrayOfInt>
    

    XmlSerializer的示范工作.Net fiddle

    正如评论中所述,ISerializable甚至没有使用XmlSerializer。它由DataContractSerializer支持,如文档here所示 - 但使用上述标准模式进行序列化将更容易。