Tuple cannot be serialized because it does not have a parameterless constructor

眉间皱痕 提交于 2019-12-06 05:50:10

The problem is that the class Tuple<T1, T2>, used by your class ListMulti among others, does not have a default constructor, as tuples can only be publicly created via Tuple.Create(). XmlSerializer, however, requires classes to have parameterless default constructors and will throw an exception if it encounters a type without a default constructor. This is the exception you are seeing.

One workaround is to add proxy properties to your class that repackage and return its data in a form that can be serialized. Then, mark the "real" properties with XmlIgnore. For the collections of string tuples held by ListMulti, a string [][] proxy property would make sense:

public class ListMulti : ParamType
{
    [XmlArray("ListMultiItems")]
    [XmlArrayItem("Pair")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public string[][] SerializableListMultiItems
    {
        get
        {
            return ListMultiItems.ToPairArray();
        }
        set
        {
            ListMultiItems.SetFromPairArray(value);
        }
    }

    [XmlArray("SelectedItemsListMulti")]
    [XmlArrayItem("Pair")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public string[][] SerializableSelectedItemsListMulti
    {
        get
        {
            return SelectedItemsListMulti.ToPairArray();
        }
        set
        {
            SelectedItemsListMulti.SetFromPairArray(value);
        }
    }

    private ObservableCollection<Tuple<string, string>> _listMultiItems = new ObservableCollection<Tuple<string, string>>();

    [XmlIgnore]
    public ObservableCollection<Tuple<string, string>> ListMultiItems
    {
        get { return _listMultiItems; }
        set { SetProperty(ref _listMultiItems, value); }
    }

    private ObservableCollection<Tuple<string, string>> _selectedListMulti;

    [XmlIgnore]
    public ObservableCollection<Tuple<string, string>> SelectedItemsListMulti
    {
        get { return _selectedListMulti ?? (_selectedListMulti = new ObservableCollection<Tuple<string, string>>()); }
        set
        {
            SetProperty(ref _selectedListMulti, value);
        }
    }
}

Using the extension methods:

public static class TupleExtensions
{
    public static T[][] ToPairArray<T>(this IEnumerable<Tuple<T, T>> collection)
    {
        return collection == null ? null : collection.Select(t => new[] { t.Item1, t.Item2 }).ToArray();
    }

    public static void SetFromPairArray<T>(this ICollection<Tuple<T, T>> collection, T[][] array)
    {
        if (collection == null)
            throw new ArgumentNullException();
        collection.Clear();
        foreach (var pair in array)
        {
            if (pair.Length != 2)
                throw new ArgumentException("Inner array did not have length 2");
            collection.Add(Tuple.Create(pair[0], pair[1]));
        }
    }
}

You'll need to make a similar fix to ListSingle.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!