2013-05-02 33 views
2

我想序列化一个包含作为成员的不可变集合的protobuf-net的类。用protobuf-net序列化不可变集合

集合类型ImmutableList<T>实现ICollection<T>,但返回trueIsReadOnly属性。所以任何修改它的尝试都会抛出异常。

Protobuf-net似乎依靠能够在创建集合以便填充它之后调用Add(T)。这显然不会对一个不可变的集合起作用,这是一种遗憾,因为protobuf-net与所有其他数据类型(它们也是不可变的)完美地协作。

所以我的问题是,我必须能够序列化这些集合有哪些选项?


ImmutableList<T>的代码如下:

public sealed class ImmutableList<T> : IList<T>, IList 
{ 
    private readonly T[] m_Items; 

    public ImmutableList(IEnumerable<T> source) 
    { 
     m_Items = source.ToArray(); 
    } 

    public T[] ToArray() 
    { 
     T[] newArray = new T[m_Items.Length]; 
     m_Items.CopyTo(newArray, 0); 
     return newArray; 
    } 

    private static void ThrowNotSupported() 
    { 
     throw new NotSupportedException("The attempted operation was not supported as the collection is read-only."); 
    } 

    #region IList<T> Members 

    int IList.Add(object value) 
    { 
     ThrowNotSupported(); 
     return -1; 
    } 

    void IList.Clear() 
    { 
     ThrowNotSupported(); 
    } 

    void IList<T>.Insert(int index, T item) 
    { 
     ThrowNotSupported(); 
    } 

    void IList.Insert(int index, object value) 
    { 
     ThrowNotSupported(); 
    } 

    void IList.Remove(object value) 
    { 
     ThrowNotSupported(); 
    } 

    void IList.RemoveAt(int index) 
    { 
     ThrowNotSupported(); 
    } 

    void IList<T>.RemoveAt(int index) 
    { 
     ThrowNotSupported(); 
    } 

    T IList<T>.this[int index] 
    { 
     get 
     { 
      return m_Items[index]; 
     } 
     set 
     { 
      ThrowNotSupported(); 
     } 
    } 

    object IList.this[int index] 
    { 
     get 
     { 
      return m_Items[index]; 
     } 
     set 
     { 
      ThrowNotSupported(); 
     } 
    } 

    public T this[int index] 
    { 
     get 
     { 
      return m_Items[index]; 
     } 
    } 

    bool IList.Contains(object value) 
    { 
     return Array.IndexOf(m_Items, value) != -1; 
    } 

    int IList.IndexOf(object value) 
    { 
     return Array.IndexOf(m_Items, value); 
    } 

    public int IndexOf(T item) 
    { 
     return Array.IndexOf(m_Items, item); 
    } 

    bool IList.IsFixedSize 
    { 
     get 
     { 
      return true; 
     } 
    } 

    #endregion 

    #region ICollection<T> Members 

    void ICollection<T>.Add(T item) 
    { 
     ThrowNotSupported(); 
    } 

    void ICollection<T>.Clear() 
    { 
     ThrowNotSupported(); 
    } 

    bool ICollection<T>.Remove(T item) 
    { 
     ThrowNotSupported(); 
     return false; 
    } 

    object ICollection.SyncRoot 
    { 
     get 
     { 
      return m_Items; 
     } 
    } 

    bool ICollection.IsSynchronized 
    { 
     get 
     { 
      return true; 
     } 
    } 

    public bool Contains(T item) 
    { 
     return IndexOf(item) != -1; 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     m_Items.CopyTo(array, arrayIndex); 
    } 

    void ICollection.CopyTo(Array array, int index) 
    { 
     m_Items.CopyTo(array, index); 
    } 

    public int Count 
    { 
     get 
     { 
      return m_Items.Length; 
     } 
    } 

    public bool IsReadOnly 
    { 
     get 
     { 
      return true; 
     } 
    } 

    #endregion 

    #region IEnumerable<T> Members 

    public IEnumerator<T> GetEnumerator() 
    { 
     return ((IEnumerable<T>)m_Items).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return m_Items.GetEnumerator(); 
    } 

    #endregion 
} 
+0

** Marc Gravell:**您是否有任何想法可以解决这个问题?如果你知道你想如何完成,我不介意帮助实施。 – 2013-05-02 04:10:36

回答

2

目前存在的不支持;但似乎是一个合理的情况。这取决于你的意思(评论)“开箱即用”;如果你的意思是“今天没有代码改变”,那么它需要使用一个反对DTO的代理,或者一个将不可变列表作为可变列表的shim属性;如果你的意思是“向前移动”,我怀疑我们可以看看采用(完善的)IEnumerable[<T>]或(不太可取,但可行)T[]的列表构造函数,并且简单地在缓冲数据之后构造列表。

+0

谢谢,你回答了我的两个问题。评论是针对前进的,最初的问题是针对今天。 – 2013-05-03 02:08:39

+0

关于前进,这是你接受补丁的东西吗? – 2013-05-03 02:45:14

+0

@JacobStanley当然,如果它工作,有一定程度的测试,并没有打破现有的代码。但是:请注意protobuf-net做了很多元编程,所以除非你对'ILGenerator'非常熟悉,否则你可能想等我看看它 – 2013-05-03 21:41:22