当前位置:  开发笔记 > 编程语言 > 正文

.NET XML序列化陷入困境?

如何解决《.NETXML序列化陷入困境?》经验,为你挑选了9个好方法。

在进行我认为我要分享的C#XML序列化时,我遇到了一些问题:

您无法序列化只读项目(如KeyValuePairs)

您无法序列化通用字典.相反,请尝试这个包装类(来自http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx):


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

[XmlRoot("dictionary")]
public class SerializableDictionary : Dictionary, IXmlSerializable
{      
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }
}

还有其他任何XML序列化吗?



1> Kalid..:

另一个巨大的问题:当通过网页(ASP.NET)输出XML时,您不希望包含Unicode字节顺序标记.当然,使用或不使用BOM的方式几乎相同:

坏(包括BOM):

XmlTextWriter wr = new XmlTextWriter(stream, new System.Text.Encoding.UTF8);

好:

XmlTextWriter  wr = new XmlTextWriter(stream, new System.Text.UTF8Encoding(false))

您可以显式传递false以指示您不需要BOM.注意Encoding.UTF8和之间明显的区别UTF8Encoding.

开头的三个额外BOM字节是(0xEFBBBF)或(239 187 191).

参考:http://chrislaco.com/blog/troubleshooting-common-problems-with-the-xmlserializer/


-1:与问题无关,你不应该在.NET 2.0或更高版本中使用`XmlTextWriter`.
如果您不仅告诉我们什么,而且告诉我们原因,您的评论会更有用.

2> Charles Grah..:

我还不能发表评论,所以我将评论Dr8k的帖子并再做一次观察.作为公共getter/setter属性公开的私有变量,并通过这些属性进行序列化/反序列化.我们在我以前的工作中做到了.

需要注意的一点是,如果这些属性中有任何逻辑,则运行逻辑,因此有时序列化的顺序实际上很重要.成员按照它们在代码中的排序方式进行隐式排序,但是没有任何保证,特别是当您继承另一个对象时.明确地命令他们是后方的痛苦.

我过去一直被这个烧了.


我在搜索显式设置字段顺序的方法时发现了这篇文章.这是通过属性完成的:[XmlElementAttribute(Order = 1)] public int Field {...}下行:必须为类中的所有字段及其所有后代指定属性!IMO你应该把它添加到你的帖子.

3> realgt..:

从内存流序列化为XML字符串时,请务必使用MemoryStream#ToArray()而不是MemoryStream#GetBuffer(),否则最终会得到不能正确反序列化的垃圾字符(因为分配了额外的缓冲区).

http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(VS.80).aspx


直接来自文档"请注意,缓冲区包含可能未使用的已分配字节.例如,如果将字符串"test"写入MemoryStream对象,则从GetBuffer返回的缓冲区长度为256,而不是4,具有252字节要仅获取缓冲区中的数据,请使用ToArray方法;但是,ToArray会在内存中创建数据的副本." http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(VS.80).aspx

4> Allon Guraln..:

如果序列化程序遇到具有接口作为其类型的成员/属性,则它将不会序列化.例如,以下内容不会序列化为XML:

public class ValuePair
{
    public ICompareable Value1 { get; set; }
    public ICompareable Value2 { get; set; }
}

虽然这将序列化:

public class ValuePair
{
    public object Value1 { get; set; }
    public object Value2 { get; set; }
}



5> 小智..:

IEnumerables通过收益率收益生成的是不可序列化的.这是因为编译器生成一个单独的类来实现yield return,并且该类未标记为可序列化.



6> Tim Robinson..:

您无法序列化只读属性.即使您从未打算使用反序列化将XML转换为对象,您也必须拥有getter和setter.

出于同样的原因,您无法序列化返回接口的属性:反序列化器不知道要实例化的具体类.



7> Eric Z Beard..:

哦,这是一个很好的:因为XML序列化代码是生成并放在一个单独的DLL中,所以当代码中的错误打破了序列化程序时,您不会收到任何有意义的错误.就像"无法找到s3d3fsdf.dll"之类的东西.尼斯.


您可以使用XML"Serializer Generator Tool(Sgen.exe)"提前生成该DLL,并使用您的应用程序进行部署.

8> Benjol..:

无法序列化没有无参数构造的对象(只是被那个人咬了).

出于某种原因,从以下属性中,Value被序列化,但不是FullName:

    public string FullName { get; set; }
    public double Value { get; set; }

我从来没有弄清楚为什么,我只是将价值改为内部......


无参数构造函数可以是private/protected.对于XML序列化程序来说就足够了.FullName的问题真的很奇怪,不应该发生......

9> Max Galkin..:

还有一点需要注意:如果使用"默认"XML序列化,则无法序列化私有/受保护类成员.

但是,您可以在类中指定实现IXmlSerializable的自定义XML序列化逻辑,并序列化您需要/想要的任何私有字段.

http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

推荐阅读
个性2402852463
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有