Reputation: 4824
I'm trying to serialize a class with protobuf-net which contains an immutable collection as a member.
The collection type, ImmutableList<T>
, implements ICollection<T>
but returns true
for the IsReadOnly
property. So any attempts to modify it throw an exception.
Protobuf-net seems to rely on being able to call Add(T)
after creating a collection in order to populate it. This obviously won't work with an immutable collection, which is a shame because protobuf-net works beautifully with all my other data types, which are also immutable.
So my question is, what options do I have to be able to serialize such collections?
The code for ImmutableList<T>
is listed below:
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
}
Upvotes: 2
Views: 1011
Reputation: 1063403
At the moment there is no support for that; but it seems a reasonable scenario. It depends on what you mean (comments) by "out of the box"; if you mean "today, without code changed", it would need to use a surrogate against the DTO, or a shim property that exposed the immutable list as a mutable one; if you mean "moving forwards", I suspect we could look at list-constructors that take (perferable) IEnumerable[<T>]
or (less preferable, but doable) T[]
, and simply construct the list after buffering the data.
Upvotes: 2