用XmlDocument属性序列化对象

本文关键字:对象 序列化 属性 XmlDocument | 更新日期: 2023-09-27 18:12:49

我有很多包含XmlDocument类型的字段和属性的类。当我把这些类的对象放在会话中(如state Server, SQL state Server)时,有必要对它们进行序列化。但是如果我们有一个XmlDocument类型的属性并在我们的类上面添加[Serialize] Attribute,就会出现以下错误。

无法序列化会话状态。在《永远的美国》和SQLServer模式,ASP。. NET将序列化会话状态对象,因此,不可序列化的对象或MarshalByRef对象是不允许的。同样的限制也适用于类似的序列化是由自定义会话状态存储在' custom '模式下完成的。

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

用XmlDocument属性序列化对象

内部,根据文档,状态服务器使用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; } }
}

结构体中的隐式操作符处理从包装器到包装器的自动转换。