本文介绍了XmlSerializer的和IEnumerable:序列化可能的W / O参数的构造函数:错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的项目中,我们extensivly使用XmlSerializer的。一次偶然的机会,我发现一个类W / OA参数的构造器。我认为这必须打破序列化进程,但事实并非如此。

通过研究这个问题,我发现,这XmlSerializer的序列化/反序列化的行为时,一个奇怪的的IEnumerable 的:

  • 可枚举的所有元素序列
  • 类是实施的添加(对象)要求的方法
  • 在它忽略了,可能是在这个类中的所有其他属性。
  • 在它调用与这个属性的getter和重用序列化的返回的实例(允许XmlSerializer的工作瓦特/ OA参数的构造函数)。

请看看下面的例子。野趣部分是ODD1,ODD2。需要注意的是good5和good6都是假的,我希望他们是真的。

还有一个原因是对这种行为?

我可以手动执行时的IXmlSerializable XmlSerializer的重用反序列化的属性返回一个实例?

  System.Collections中使用;
使用System.Collections.Generic;
使用System.IO;
使用的System.Xml;
使用System.Xml.Schema;
使用的System.Xml.Serialization;

命名空间测试
{
    公共静态类节目
    {
        公共静态无效的主要()
        {
            HostingClass主机=新HostingClass();

            host.AutomaticSerialization.StringProperty =自动;
            host.SelfImplementedSerialization.StringProperty =自我;

            布尔good1 = host.AutomaticSerialization.FromConstructor ==参数;
            布尔good2 = host.SelfImplementedSerialization.FromConstructor ==参数;
            布尔good3 = host.AutomaticSerialization.StringProperty ==AUTO;
            布尔good4 = host.SelfImplementedSerialization.StringProperty ==自我;

            XmlSerializer的序列化=新的XmlSerializer(typeof运算(HostingClass));

            使用(StringWriter的SW =新的StringWriter())
            {
                serializer.Serialize(SW,主机);

                用(StringReader SR =新StringReader(sw.ToString()))
                {
                    主机=(HostingClass)serializer.Deserialize(SR);
                }
            }

            布尔good5 = host.AutomaticSerialization.FromConstructor == NULL; //为假
            布尔good6 = host.AutomaticSerialization.StringProperty ==AUTO; //为假

            布尔good7 = host.SelfImplementedSerialization.FromConstructor == NULL;
            布尔good8 = host.SelfImplementedSerialization.StringProperty ==自我;

        }
    }

    公共类HostingClass
    {
        私人SelfImplementedSerialization _selfImplementedSerialization;
        公共SelfImplementedSerialization SelfImplementedSerialization
        {
            得到
            {
                返回_selfImplementedSerialization
                       ? (_selfImplementedSerialization =新SelfImplementedSerialization(参数));
            }
            集合{_selfImplementedSerialization =价值; }
        }

        私人AutomaticSerialization _automaticSerialization;
        公共AutomaticSerialization AutomaticSerialization
        {
            得到
            {
                返回_automaticSerialization
                       ? (_automaticSerialization =新AutomaticSerialization(参数)); //反序列化返回的对象用于
            }
            集合{_automaticSerialization =价值; }
        }
    }

    公共类SelfImplementedSerialization:IXmlSerializable的,IEnumerable的< INT>
    {
        公共SelfImplementedSerialization(){}
        公共SelfImplementedSerialization(字符串参数)
        {
            FromConstructor =参数;
        }

        公共字符串StringProperty {获得;组; }
        [XmlIgnore]
        公共字符串FromConstructor {获得;组; }

        公共无效的ReadXml(XmlReader的读者)
        {
            reader.ReadStartElement();
            StringProperty = reader.ReadElementString(StringProperty);
            reader.ReadEndElement();
        }

        公共无效中WriteXML(XmlWriter的作家)
        {
            writer.WriteElementString(StringProperty,StringProperty);
        }

        公众的IEnumerator< INT>的GetEnumerator()
        {
            收益率的回报1;
            收益率回归2;
        }

        IEnumerator的IEnumerable.GetEnumerator(){返回的GetEnumerator(); }
        公众的XmlSchema的getSchema(){返回NULL; }
    }


    公共类AutomaticSerialization:IEnumerable的<诠释>
    {
        // ODD1:序列​​化可能的W / O型的公共参数构造函数
        //公共AutomaticSerialization(){}
        公共AutomaticSerialization(字符串参数)
        {
            FromConstructor =参数;
        }

        // ODD2:元素没有序列号,只有IEnumerable接口是序列化
        [的XmlElement(SP)]
        公共字符串StringProperty {获得;组; }
        [XmlIgnore]
        公共字符串FromConstructor {获得;组; }

        公众的IEnumerator< INT>的GetEnumerator()
        {
            收益率的回报1;
            收益率回归2;
        }

        公共无效添加(对象o)
        {
            XmlSerializer的序列化的时候IEnumerables //要求
        }

        IEnumerator的IEnumerable.GetEnumerator(){返回的GetEnumerator(); }
    }
}
 

解决方案

的原因行为,这是它一贯的工作方式。

XmlSerializer类

In our project we extensivly use the XmlSerializer. By chance I found a class w/o a parameterless contructor. I thought this must break the serialization process but it did not.

By investigating this issue I found out, that the XmlSerializer behaves strange when serializing/deserializing an IEnumerable:

  • All elements of the enumerable are serialized
  • The class is required to implement an Add(object) method
  • It ignores all other properties that may be in this class.
  • It calls a getter with this property and reuses the returned instance for serialization (which allows the XmlSerializer to work w/o a parameterless constructor).

Please have a look at the example that follows. Intersting parts are ODD1, ODD2. Note that good5 and good6 are false, when I expected them to be true.

Is there a reason for this behaviour?

Can I make XmlSerializer reuse an instance returned by a property for deserialization when implementing IXmlSerializable by hand?

using System.Collections;
using System.Collections.Generic;   
using System.IO;    
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace Test
{
    public static class Program
    {
        public static void Main()
        {
            HostingClass host = new HostingClass();

            host.AutomaticSerialization.StringProperty = "AUTO";
            host.SelfImplementedSerialization.StringProperty = "SELF";

            bool good1 = host.AutomaticSerialization.FromConstructor == "PARAMETER";
            bool good2 = host.SelfImplementedSerialization.FromConstructor == "PARAMETER";
            bool good3 = host.AutomaticSerialization.StringProperty == "AUTO";
            bool good4 = host.SelfImplementedSerialization.StringProperty == "SELF";

            XmlSerializer serializer = new XmlSerializer(typeof(HostingClass));

            using (StringWriter sw = new StringWriter())
            {
                serializer.Serialize(sw, host);

                using (StringReader sr = new StringReader(sw.ToString()))
                {
                    host = (HostingClass)serializer.Deserialize(sr);
                }
            }

            bool good5 = host.AutomaticSerialization.FromConstructor == null; //is false
            bool good6 = host.AutomaticSerialization.StringProperty == "AUTO"; //is false

            bool good7 = host.SelfImplementedSerialization.FromConstructor == null;
            bool good8 = host.SelfImplementedSerialization.StringProperty == "SELF";

        }
    }

    public class HostingClass
    {
        private SelfImplementedSerialization _selfImplementedSerialization;
        public SelfImplementedSerialization SelfImplementedSerialization
        {
            get
            {
                return _selfImplementedSerialization
                       ?? (_selfImplementedSerialization = new SelfImplementedSerialization("PARAMETER"));
            }
            set { _selfImplementedSerialization = value; }
        }

        private AutomaticSerialization _automaticSerialization;
        public AutomaticSerialization AutomaticSerialization
        {
            get
            {
                return _automaticSerialization
                       ?? (_automaticSerialization = new AutomaticSerialization("PARAMETER")); //the returned object is used while deserializing
            }
            set { _automaticSerialization = value; }
        }
    }

    public class SelfImplementedSerialization : IXmlSerializable, IEnumerable<int>
    {
        public SelfImplementedSerialization() { }
        public SelfImplementedSerialization(string parameter)
        {
            FromConstructor = parameter;
        }

        public string StringProperty { get; set; }
        [XmlIgnore]
        public string FromConstructor { get; set; }

        public void ReadXml(XmlReader reader)
        {
            reader.ReadStartElement();
            StringProperty = reader.ReadElementString("StringProperty");
            reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteElementString("StringProperty", StringProperty);
        }

        public IEnumerator<int> GetEnumerator()
        {
            yield return 1;
            yield return 2;
        }

        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
        public XmlSchema GetSchema() { return null; }
    }


    public class AutomaticSerialization : IEnumerable<int>
    {
        //ODD1: Serialization possible w/o public parameterless constructor
        //public AutomaticSerialization() {} 
        public AutomaticSerialization(string parameter)
        {
            FromConstructor = parameter;
        }

        //ODD2: Element not serialized, only the IEnumerable Interface is serialized
        [XmlElement("SP")]
        public string StringProperty { get; set; }
        [XmlIgnore]
        public string FromConstructor { get; set; }

        public IEnumerator<int> GetEnumerator()
        {
            yield return 1;
            yield return 2;
        }

        public void Add(object o)
        {
            //requirement of XmlSerializer when serializing IEnumerables
        }

        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
    }
}
解决方案

The reason for the behavior is that this is the way it has always worked.

From XmlSerializer class:

这篇关于XmlSerializer的和IEnumerable:序列化可能的W / O参数的构造函数:错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 16:49