1

type のいくつかのフィールドとプロパティを含む多くのクラスが必要XmlDocumentです。これらのクラスのオブジェクト (状態サーバー、SQL 状態サーバーなど) をセッションに配置するときは、それらをシリアル化する必要があります。しかし、タイプ XmlDocument のプロパティがあり [Serialize]、クラスの上に Attribute を追加すると、次のエラーが表示されます。

セッション状態をシリアル化できません。'StateServer' および 'SQLServer' モードでは、ASP.NET はセッション状態オブジェクトをシリアル化するため、シリアル化できないオブジェクトまたは MarshalByRef オブジェクトは許可されません。「カスタム」モードのカスタム セッション状態ストアによって同様のシリアル化が行われる場合、同じ制限が適用されます。

[NonSerialize]フィールドが属性を持っている場合、このエラーは表示されません。[NonSerialize]クラスと構造体とイベントとデリゲートにのみ使用できるため、プロパティに属性を含めることはできません。

4

1 に答える 1

2

内部的には、docsによると、状態サーバーはBinaryFormatter複雑な型をシリアル化するために使用します。 としてマークされたクラスまたは構造体のBinaryFormatterすべてのパブリックおよびプライベートフィールド[Serializable](プロパティではありません!) をシリアル化します。しかしXmlDocument、あなたが指摘したように、 はそれほどマークされていないため、 ですぐにシリアル化することはできませんBinaryFormatter

XmlDocumentただし、文字列 (ドキュメントが表す XML 自体) との間で簡単に変換できます。したがって、XmlDocumentフィールドが を実装する型に含まれている場合ISerializableGetObjectData()対応する 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; } }
}

構造体の暗黙の演算子は、ラッパーとの間の自動変換を処理します。

于 2015-09-15T10:05:02.770 に答える