Сериализация объекта с помощью свойства XmlDocument
У меня есть много классов, которые содержат некоторые поля и свойства типа XmlDocument
, Когда я помещаю объекты этих классов в сессию (например, State Server, SQL State Server), необходимо их сериализовать. Но если у нас есть свойство типа XmlDocument и добавить [Serialize]
Атрибут выше нашего класса, появится следующая ошибка.
Невозможно сериализовать состояние сеанса. В режимах "StateServer" и "SQLServer" ASP.NET сериализует объекты состояния сеанса, и в результате несериализуемые объекты или объекты MarshalByRef не допускаются. То же ограничение применяется, если аналогичная сериализация выполняется в пользовательском хранилище состояний сеанса в режиме "Пользовательский".
эта ошибка не отображается для полей [NonSerialize]
приписывать. свойства не могут иметь атрибут [NonSerialize]
потому что это может использоваться только для класса и структуры и события и делегата.
1 ответ
Внутренне, в соответствии с документами, сервер состояний использует 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; } }
}
Неявные операторы в структуре обрабатывают автоматическое преобразование из и в оболочку.