我必须使用许多类,其中包含[Serialize]
类型的一些字段和属性。
当我将这些类的对象放在会话中(例如状态服务器,SQL状态服务器)时,有必要对它们进行序列化。
但是如果我们有一个XmlDocument类型的属性并在我们的类上面添加[NonSerialize]
属性,则会出现以下错误。
无法序列化会话状态。在' StateServer'和 ' SQLServer的'模式,ASP.NET将序列化会话状态对象, 因此,不可序列化的对象或MarshalByRef对象是 不允许。如果类似的序列化,则适用相同的限制 由自定义会话状态存储在' Custom'中完成。模式。
对于具有[NonSerialize]
属性的字段,不会显示此错误。属性不能具有属性./code/src/
,因为它只能用于类和结构以及事件和委托。
答案 0 :(得分: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; } }
}
struct中的隐式运算符处理从包装器到包装器的自动转换。