【问题标题】:serialize object with XmlDocument Property使用 XmlDocument 属性序列化对象
【发布时间】:2015-09-15 07:00:59
【问题描述】:

我有很多类包含XmlDocument 类型的一些字段和属性。 当我把这些类的对象放在会话中(比如状态服务器、SQL 状态服务器)时,就需要对它们进行序列化。 但是如果我们有一个XmlDocument类型的属性,在我们的类上面加上[Serialize]属性,就会出现如下错误。

无法序列化会话状态。在“状态服务器”和 'SQLServer' 模式,ASP.NET 将序列化会话状态对象, 结果是不可序列化的对象或 MarshalByRef 对象 不允许。如果类似的序列化,同样的限制适用 由自定义会话状态存储在“自定义”模式下完成。

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

【问题讨论】:

    标签: c# serialization xmldocument session-state-server state-server


    【解决方案1】:

    在内部,根据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; } }
    }
    

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

    【讨论】:

    • 坦克很多。它适用于 XmlDocument ,那么 XslCompiledTransform 呢?我怎样才能序列化这个类?
    • @Hadi - 我对那个课程不太熟悉。如果您能找到一种方法从类中提取 XML 样式表作为字符串(或 XmlDocument),则可以使用相同的技术。这里的问题首选格式是one question per question,所以我建议再问一个问题。
    猜你喜欢
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2015-06-18
    • 2021-08-28
    • 2015-04-20
    相关资源
    最近更新 更多