2

I am trying to serialize an instance of the QDatatables class provided below, but I am getting error :

An exception of type 'System.InvalidOperationException' occurred in System.Xml.dll but was not handled in user code Additional information: There was an error reflecting type 'System.Collections.ObjectModel.ObservableCollection`1[DataRetrieval.Model.QDatatable]'.

StackTrace: at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)

InnerException: {"System.Tuple`2[System.String,System.String] cannot be serialized because it does not have a parameterless constructor."}

Can anyone help to find what is missing?

My serlializing function:

        public string serialize()
        {
            StringWriter sw = new StringWriter();
            XmlSerializer s = new XmlSerializer(this.GetType());
            s.Serialize(sw, this);
            return sw.ToString();
        }

QDatatables class:

    [Serializable()]
    public class QDatatables : BindableBase
    {
        private ObservableCollection<QDatatable> _list;
        public ObservableCollection<QDatatable> List
        {
            get { return _list ?? (_list=new ObservableCollection<QDatatable>()); }
            set { SetProperty(ref _list, value); }
        }     
            public string serialize()
        {

            StringWriter sw = new StringWriter();
            XmlSerializer s = new XmlSerializer(typeof(ObservableCollection<QDatatable>));
            s.Serialize(sw, List);
            return sw.ToString();
        }
    }

QDatatable Class

    [Serializable()]
    public class QDatatable : BindableBase
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { SetProperty(ref _id, value); }
        }
        private String _name;
        public String Name
        {
            get { return _name; }
            set { SetProperty(ref _name, value); }
        }
        private WhereParams _params;
        public WhereParams Params
        {
            get { return _params; }
            set { SetProperty(ref _params, value); }
        }

        private bool _isexpanded;
        public bool IsExpanded
        {
            get { return _isexpanded; }
            set { SetProperty(ref _isexpanded, value); }
        }
    }

WhereParam Class:

    public class WhereParams : BindableBase
    {
        private Dictionary<int, WhereParam> _dictionaryIdToWhereParam;

        private ObservableCollection<WhereParam> _list;
        public ObservableCollection<WhereParam> List
        {
            get { return _list ?? (_list = new ObservableCollection<WhereParam>()); }
            set { SetProperty(ref _list, value); }
        }
        public WhereParam GetById(int id)
        {
            return List.First(w => w.ID == id);
        }
        public string serialize()
        {
            StringWriter sw = new StringWriter();
            XmlSerializer s = new XmlSerializer(this.GetType());
            s.Serialize(sw, this);
            return sw.ToString();
        }
    }

    [Serializable()]
    public class WhereParam:BindableBase
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { SetProperty(ref _id, value); }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { SetProperty(ref _name, value); }
        }
        private ParamType _type;
        public ParamType Type
        {
            get { return _type; }
            set { SetProperty(ref _type, value); }
        }    
    }

ParamType Class:

   [XmlInclude(typeof(DateTimeType))]
   [XmlInclude(typeof(StringType))]
   [XmlInclude(typeof(IntType))]
   [XmlInclude(typeof(FloatgType))]
   [XmlInclude(typeof(BoolType))]
   [XmlInclude(typeof(NullableBoolType))]
   [XmlInclude(typeof(ListMulti))]
   [XmlInclude(typeof(ListSingle))]
   [XmlInclude(typeof(StringMulti))]
    public class ParamType: BindableBase
    {
        private int _typeID;
        public int TypeID
        {
            get { return _typeID; }
            set { SetProperty(ref _typeID, value); }
        }

        private ParamTypeEnum _typeName;
        public ParamTypeEnum TypeName
        {
            get { return _typeName; }
            set { SetProperty(ref _typeName, value); }
        }

    }

   public class DateTimeType : ParamType
    {

        private DateTime? _datefrom;
        public DateTime? Datefrom
        {
            get { return _datefrom; }
            set { SetProperty(ref _datefrom, value); }
        }

        private DateTime? _dateTo;
        public DateTime? DateTo
        {
            get { return _dateTo; }
            set { 
                SetProperty(ref _dateTo, value); }
        }


    }
    public class StringType : ParamType
    {

        private string _stringContent;
        public string StringContent
        {
            get { return _stringContent; }
            set { 
                SetProperty(ref _stringContent, value); }
        }



    }
    public class IntType : ParamType
    {

        private int _intContent;
        public int IntContent
        {
            get { return _intContent; }
            set { SetProperty(ref _intContent, value); }
        }



    }
    public class FloatgType : ParamType
    {

        private float _floatContent;
        public float FloatContent
        {
            get { return _floatContent; }
            set { SetProperty(ref _floatContent, value); }
        }


    }
    public class BoolType : ParamType
    {

        private bool _boolTypeValue;
        public bool BoolTypeValue
        {
            get { return _boolTypeValue; }
            set { SetProperty(ref _boolTypeValue, value); }
        }


    }
    public class NullableBoolType : ParamType
    {

        private bool? _nullableBoolTypeValue;
        public bool? NullableBoolTypeValue
        {
            get { return _nullableBoolTypeValue; }
            set { SetProperty(ref _nullableBoolTypeValue, value); }
        }


    }
    public class ListMulti : ParamType
    {

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


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




    }
    public class ListSingle : ParamType
    {
        private ObservableCollection<Tuple<string, string>> _listSingleItems;
        public ObservableCollection<Tuple<string, string>> ListSingleItems
        {
            get { return _listSingleItems; }
            set { SetProperty(ref _listSingleItems, value); }
        }

        //private ObservableCollection<Tuple<string, string>> _listSingleItems;
        //public ObservableCollection<Tuple<string, string>> ListSingleItems
        //{
        //    get { return _listSingleItems; }
        //    set { SetProperty(ref _listSingleItems, value); }
        //}



    }
    public class StringMulti : ParamType
    {

        private string _listMultiCollection;
        public string ListMultiCollection
        {
            get { return _listMultiCollection; }
            set { SetProperty(ref _listMultiCollection, value); }
        }


    }
    public enum ParamTypeEnum
    {
        boolType,
        nullableboolType,
        intType,
        floatType,
        stringType,
        datetimeType,
        listmultiType,
        stringlistmultiType,

    };
15
  • 1
    Is DateTimeType private? If so, modify it as public. Commented Oct 20, 2015 at 0:45
  • Can you edit your question to include the full ToString() output of the exception including the traceback and inner exception? The inner exception will probably tell you what you need. Commented Oct 20, 2015 at 1:20
  • @SeongTaeJeong its public already ! Commented Oct 20, 2015 at 1:32
  • In your question, class DateTimeType : ParamType is not prefaced with public, so it's a private type. XmlSerializer can only serialize public types. Commented Oct 20, 2015 at 1:36
  • 1
    Did you forget to mark you WhereParams class with the SerializableAttribute? Also are you doing anything with the dictionary in that class? Commented Oct 20, 2015 at 1:46

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@dpc Thank you, that solved my issue. But its a little bit complicated ! I hope I can create the similar fix for my other Tuples !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.