繁体   English   中英

使用XmlDocument属性序列化对象

[英]serialize object with XmlDocument Property

我必须拥有许多包含XmlDocument类型的字段和属性的类。 当我将这些类的对象放入会话(例如状态服务器,SQL状态服务器)时,有必要对其进行序列化。 但是,如果我们具有XmlDocument类型的属性,并在类上方添加[Serialize]属性,则会出现以下错误。

无法序列化会话状态。 在“ StateServer”和“ SQLServer”模式下,ASP.NET将序列化会话状态对象,因此,不允许不可序列化的对象或MarshalByRef对象。 如果自定义会话状态存储在“自定义”模式下进行了类似的序列化,则存在相同的限制。

对于具有[NonSerialize]属性的字段,不会出现此错误。 这些属性不能具有[NonSerialize]属性,因为它只能用于类和结构以及事件和委托。

在内部,根据docs ,状态服务器使用BinaryFormatter序列化复杂类型。 BinaryFormatter序列化标记为[Serializable]的类或结构的所有公共和私有字段 (不是属性!)。 但是,正如您已经指出的那样, XmlDocument并不是这样标记的,因此不能立即使用BinaryFormatter进行序列化。

但是,可以简单地将XmlDocument转换为字符串,即文档表示的XML本身。 因此,如果XmlDocument字段包含在实现ISerializable的类型中,则其GetObjectData()可以简单地将相应的XML字符串存储在序列化流中。 然后,相应的序列化构造函数可以提取XML字符串并重新构造XmlDocument

由于在预先存在的类上实现ISerializable可能很耗时,因此,完成所需操作的最简单方法是为XML文档引入一个小的序列化包装器结构:

[Serializable]
public struct XmlDocumentSerializationWrapper : ISerializable
{
    public static implicit operator XmlDocumentSerializationWrapper(XmlDocument data) { return new XmlDocumentSerializationWrapper(data); }

    public static implicit operator XmlDocument(XmlDocumentSerializationWrapper wrapper) { return wrapper.XmlDocument; }

    private readonly XmlDocument xmlDocument;

    public XmlDocument XmlDocument { get { return xmlDocument; } }

    public XmlDocumentSerializationWrapper(XmlDocument xmlDocument)
    {
        this.xmlDocument = xmlDocument;
    }

    public XmlDocumentSerializationWrapper(SerializationInfo info, StreamingContext context)
    {
        var xml = (string)info.GetValue("XmlDocument", typeof(string));
        if (!string.IsNullOrEmpty(xml))
        {
            xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(xml);
        }
        else
        {
            xmlDocument = null;
        }
    }

    #region ISerializable Members

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (XmlDocument != null)
        {
            var xml = XmlDocument.OuterXml;
            info.AddValue("XmlDocument", xml);
        }
        else
        {
            info.AddValue("XmlDocument", (string)null);
        }
    }

    #endregion
}

然后,在要序列化的类中,将XmlDocument字段(和自动实现的属性)替换为包装结构字段,例如:

[Serializable]
public class TestClass
{
    XmlDocumentSerializationWrapper doc;

    public XmlDocument Document { get { return doc; } set { doc = value; } }
}

结构中的隐式运算符处理包装器之间的自动转换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM