Подтвердить что ты не робот

Почему я не мог сериализовать кортеж в С#?

Возможный дубликат:
Почему классу XML-Serializable нужен конструктор без параметров

Я пытаюсь сериализовать кортеж в своем коде:

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();

но он был провален и поймал исключение, подобное этому:

System.Tuple`2 [System.String, CodeExtractor.StatementNode] не может быть сериализован, потому что у него нет конструктора без параметров.

и я уверен, что CodeExtractor.StatementNode может быть сериализован.

4b9b3361

Ответ 1

Для XmlSerializer, чтобы иметь возможность выполнять свою работу, нужен конструктор по умолчанию. Это конструктор, который не принимает аргументов. Все классы Tuple <... > имеют один конструктор и этот конструктор принимает несколько аргументов. Один для каждого значения в кортеже. Поэтому в вашем случае единственным конструктором является

Tuple(T1 value1, T2 value2)

Сериализатор ищет конструктор без аргументов, и поскольку он не может его найти, вы получаете исключение.

вы можете создать изменяемый класс, который может быть заменен кортежами с целью сериализации

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);
    }
}

Затем вы можете использовать его следующим образом

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

formatter.Serialize(fs, results.SelectMany(
                              lst => lst.Select(
                                        t => (MyTuple)t
                                     ).ToList()
                              ).ToList());

Ответ 2

Как исключение говорит вам: Tuple<T1, T2> не имеет конструктора без параметров, который необходим сериализатору.