0

I am working with the BlockingCollection and have run into issues in attempting to serialize it. The error occurs on the new XmlSerializer line. The error is:

You must implement a default accessor on System.Collections.Concurrent.BlockingCollection`1[[BlockingCollTest.MyItem, BlockingCollTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] because it inherits from ICollection.

The test program is:

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace BlockingCollTest
{
    class Program
    {
        static void Main(string[] args)
        {
            BlockingCollection<MyItem> c = new BlockingCollection<MyItem>();
            c.Add(new MyItem("001", "Smith"));
            c.Add(new MyItem("002", "Johnson"));

            XmlSerializer serializer = new XmlSerializer(typeof(BlockingCollection<MyItem>));
        }
    }
    [Serializable]
    public class MyItem
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public MyItem() { }
        public MyItem(string id, string name) { ID = id; Name = name; }
    }
}

After trying several solutions and I am at a loss to understand how to solve this error.

Question: What is required to solve the serialization of a BlockingCollection issue?

S.Davis
  • 3
  • 1
  • 3
    Serializing a class that is intended as a thread-safe collection is highly questionable. A workaround is use its ToArray() method and serialize the array. – Hans Passant Jan 11 '16 at 19:25

1 Answers1

2

BlockingCollection is not attributed as [Serializable] and does not implement ISerializable. Therefore you cannot serialize it using XmlSerializer even if MyItem is Serializable. You can copy the items to a single serializable collection or array (e.g. MyItem[]), serialize it and recreate the BlockingCollection after you deserialize back.

Guy Levy
  • 1,550
  • 2
  • 15
  • 26
  • Thank you Guy. I did not catch that BlockingCollection was not serializable. Your solution makes sense. – S.Davis Jan 11 '16 at 19:33
  • Credit also goes to Hans who gave the right answer in a comment. Saw it only after submitting my answer (sorry) – Guy Levy Jan 11 '16 at 19:39
  • 2
    [`ConcurrentQueue`](https://msdn.microsoft.com/en-us/library/dd267265(v=vs.110).aspx) (the collection that is used as the underlying collection when you use the default constructor) is serializeable. If you used [this constructor](https://msdn.microsoft.com/en-us/library/dd287133(v=vs.110).aspx) and kept a reference to the queue you could have the queue be serialized then on deserialization build a new `BlockingCollection` passing the serialized queue in. Might work better than working with arrays. – Scott Chamberlain Jan 11 '16 at 19:41