2013-05-02 45 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