26

Possible Duplicate:
Why XML-Serializable class need a parameterless constructor

I'm trying to serialize a tuple in my code:

List<List<Tuple<String, CodeExtractor.StatementNode>>> results = null;
results = extractor.ExtractSourceCode(sourceCode);
FileStream fs = new FileStream(@"C:\Projects\Test\ast.xml", FileMode.Create);

XmlSerializer formatter = new XmlSerializer(
    typeof(List<List<Tuple<String, CodeExtractor.StatementNode>>>));

formatter.Serialize(fs, results);

fs.Close();

but it was failed and catch the exception like this:

System.Tuple`2[System.String,CodeExtractor.StatementNode] cannot be serialized because it does not have a parameterless constructor.

and I'm do sure the CodeExtractor.StatementNode could be serialized.

Community
  • 1
  • 1
user1278322
  • 299
  • 2
  • 4
  • 4
  • 1
    read the statement: _System.Tuple`2[System.String,System.String] cannot be serialized because it does not have a parameterless constructor_ ... it's pretty clear! (see decompilation: http://pastebin.com/b6vUMuX3) –  Dec 06 '12 at 08:07
  • Are CodeExtractor and StatementNode both serializable? – petro.sidlovskyy Dec 06 '12 at 08:07
  • see this question: http://stackoverflow.com/questions/267724/why-xml-serializable-class-need-a-parameterless-constructor – Cristian Lupascu Dec 06 '12 at 08:10

2 Answers2

34

For XmlSerializer to be able to do its job it needs a default contructor. That is a constructor that takes no arguments. All the Tuple<...> classes have a single constructor and that constructor takes a number of arguments. One for each value in the tuple. So in your case the sole constructor is

Tuple(T1 value1, T2 value2)

The serializer is looking for a constructor with no arguments and because it can't find it, you get the exception.

you could create a mutable class, that could be substituted for tuples for the purpose of serialization

class MyTuple<T1, T2>
{
    MyTuple() { }

    public T1 Item1 { get; set; }
    public T2 Item2 { get; set; }

    public static implicit operator MyTuple<T1, T2>(Tuple<T1, T2> t)
    {
         return new MyTuple<T1, T2>(){
                      Item1 = t.Item1,
                      Item2 = t.Item2
                    };
    }

    public static implicit operator Tuple<T1, T2>(MyTuple<T1, T2> t)
    {
        return Tuple.Create(t.Item1, t.Item2);
    }
}

You could then use it the following way

XmlSerializer formatter = new XmlSerializer(
    typeof(List<List<MyTuple<String, CodeExtractor.StatementNode>>>));

formatter.Serialize(fs, results.SelectMany(
                              lst => lst.Select(
                                        t => (MyTuple)t
                                     ).ToList()
                              ).ToList());
Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
Rune FS
  • 21,497
  • 7
  • 62
  • 96
1

As the exception tells you: The Tuple<T1, T2> has NO parameterless constructor which is needed by the serializer.

Emond
  • 50,210
  • 11
  • 84
  • 115