Freigeben über


CA2240: ISerializable ordnungsgemäß implementieren.

Element Wert
RuleId CA2240
Category Microsoft.Usage
Unterbrechende Änderung Nicht unterbrechend

Ursache

Der Schnittstelle System.Runtime.Serialization.ISerializable kann ein extern sichtbarer Typ zugewiesen werden, und eine der folgenden Bedingungen ist erfüllt:

Regelbeschreibung

Instanzfelder, die in einem Typ deklariert sind, der die Schnittstelle System.Runtime.Serialization.ISerializable erbt, werden nicht automatisch in den Serialisierungsprozess einbezogen. Zur Einbeziehung der Felder muss der Typ die Methode GetObjectData und den Serialisierungskonstruktor implementieren. Wenn die Felder nicht serialisiert werden sollen, wenden Sie das Attribut NonSerializedAttribute auf die Felder an, um dies ausdrücklich anzugeben.

In nicht versiegelten Typen sollten Implementierungen der GetObjectData-Methode extern sichtbar sein. Daher kann die Methode von abgeleiteten Typen aufgerufen werden und ist überschreibbar.

Behandeln von Verstößen

Um einen Verstoß gegen diese Regel zu beheben, legen Sie die GetObjectData-Methode als sichtbar und überschreibbar fest und stellen sicher, dass alle Instanzfelder in den Serialisierungsprozess einbezogen oder explizit mit dem NonSerializedAttribute-Attribut gekennzeichnet wurden.

Wann sollten Warnungen unterdrückt werden?

Unterdrücken Sie keine Warnung dieser Regel.

Beispiel 1

Das folgende Beispiel zeigt zwei serialisierbare Typen, die gegen diese Regel verstoßen.

using System;
using System.Security.Permissions;
using System.Runtime.Serialization;

namespace Samples1
{
    // Violates this rule
    [Serializable]
    public class Book : ISerializable
    {
        private readonly string _Text;

        public Book(string text)
        {
            if (text == null)
                throw new ArgumentNullException("text");

            _Text = text;
        }

        protected Book(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            _Text = info.GetString("Text");
        }

        public string Text
        {
            get { return _Text; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            info.AddValue("Text", _Text);
        }
    }

    // Violates this rule
    [Serializable]
    public class LibraryBook : Book
    {
        private readonly DateTime _CheckedOut;

        public LibraryBook(string text, DateTime checkedOut)
            : base(text)
        {
            _CheckedOut = checkedOut;
        }

        public DateTime CheckedOut
        {
            get { return _CheckedOut; }
        }
    }
}

Beispiel 2

Das folgende Beispiel behebt die zwei vorherigen Verstöße, indem eine überschreibbare Implementierung von GetObjectData in der Klasse „Book“ und eine Implementierung von GetObjectData in der Klasse „Library“ bereitgestellt wird.

using System;
using System.Security.Permissions;
using System.Runtime.Serialization;

namespace Samples2
{
    [Serializable]
    public class Book : ISerializable
    {
        private readonly string _Title;

        public Book(string title)
        {
            if (title == null)
                throw new ArgumentNullException("title");

            _Title = title;
        }

        protected Book(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            _Title = info.GetString("Title");
        }

        public string Title
        {
            get { return _Title; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Title", _Title);
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            GetObjectData(info, context);
        }
    }

    [Serializable]
    public class LibraryBook : Book
    {
        private readonly DateTime _CheckedOut;

        public LibraryBook(string title, DateTime checkedOut)
            : base(title)
        {
            _CheckedOut = checkedOut;
        }

        protected LibraryBook(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            _CheckedOut = info.GetDateTime("CheckedOut");
        }

        public DateTime CheckedOut
        {
            get { return _CheckedOut; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("CheckedOut", _CheckedOut);
        }
    }
}