元组无法序列化,因为它没有无参数构造函数 [英] Tuple cannot be serialized because it does not have a parameterless constructor

查看:58
本文介绍了元组无法序列化,因为它没有无参数构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试序列化下面提供的 QDatatables 类的实例,但出现错误:

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

System.Xml.dll 中出现类型为System.InvalidOperationException"的异常,但未在用户代码中处理附加信息:反映类型System.Collections.ObjectModel.ObservableCollection`1[DataRetrieval.Model.QDatatable]"时出现错误.

StackTrace:在 System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping 映射,StructModel 模型,Boolean openModel,String typeName,RecursionLimiter 限制器)在 System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel 模型,字符串 ns,布尔 openModel,XmlAttributes a,RecursionLimiter 限制器)在 System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)

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] 无法序列化,因为它没有无参数构造函数."}

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?

我的序列化功能:

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

QDatatables 类:

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 类

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 类:

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 类:

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,

    };

推荐答案

问题是你的类ListMulti使用的Tuple类其他人,没有默认构造函数,因为元组只能通过 Tuple.Create().XmlSerializer,但是,需要 类具有无参数的默认构造函数,如果遇到没有默认构造函数的类型,将抛出异常.这是您看到的例外情况.

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.

一种解决方法是向您的类添加代理属性,这些属性重新打包并以可序列化的形式返回其数据.然后,使用 XmlIgnore.对于 ListMulti 持有的字符串元组集合,string [][] 代理属性是有意义的:

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

使用扩展方法:

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

您需要对 ListSingle 进行类似的修复.

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

这篇关于元组无法序列化,因为它没有无参数构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆