Freigeben über


CA2240: ISerializable ordnungsgemäß implementieren

TypeName

ImplementISerializableCorrectly

CheckId

CA2240

Kategorie (Category)

Microsoft.Usage

Unterbrechende Änderung

Nicht unterbrechend

Ursache

Ein extern sichtbarer Typ kann der ISerializable-Schnittstelle zugewiesen werden, und eine der folgenden Bedingungen trifft zu:

  • Der Typ erbt die ISerializable.GetObjectData-Methode, überschreibt sie aber nicht, und der Typ deklariert Instanzenfelder, die nicht mit dem NonSerializedAttribute-Attribut markiert sind.

  • Der Typ ist nicht versiegelt und implementiert eine GetObjectData-Methode, die nicht extern sichtbar und überschreibbar ist.

Regelbeschreibung

Instanzenfelder, die in einem Typ deklariert werden, der die ISerializable-Schnittstelle erbt, werden nicht automatisch in den Serialisierungsvorgang aufgenommen.Damit die Felder aufgenommen werden, muss der Typ die GetObjectData-Methode und den Serialisierungskonstruktor implementieren.Wenn die Felder nicht serialisiert werden sollen, weisen Sie den Feldern das Attribut NonSerializedAttribute zu, um diese Entscheidung explizit anzugeben.

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

Behandeln von Verstößen

Um einen Verstoß gegen diese Regel zu beheben, stellen Sie sicher, dass die GetObjectData-Methode sichtbar und überschreibbar ist und dass alle Instanzenfelder in den Serialisierungsprozess einbezogen werden oder explizit mit dem NonSerializedAttribute-Attribut markiert sind.

Wann sollten Warnungen unterdrückt werden?

Unterdrücken Sie keine Warnung dieser Regel.

Beispiel

Im folgenden Beispiel werden zwei serialisierbare Typen veranschaulicht, die gegen die Regel verstoßen.

Imports System
Imports System.Security.Permissions
Imports System.Runtime.Serialization

Namespace Samples1

    ' Violates this rule
    <Serializable()> _
    Public Class Book
        Implements ISerializable

        Private ReadOnly _Title As String 

        Public Sub New(ByVal title As String)
            If (title Is Nothing) Then Throw New ArgumentNullException("title")
            _Title = title
        End Sub 

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            _Title = info.GetString("Title")
        End Sub 

        Public ReadOnly Property Title() As String 
            Get 
                Return _Title
            End Get 
        End Property

        <SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) _
            Implements ISerializable.GetObjectData

            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            info.AddValue("Title", _Title)
        End Sub 
    End Class 

    ' Violates this rule
    <Serializable()> _
    Public Class LibraryBook
        Inherits Book

        Private ReadOnly _CheckedOut As Date 

        Public Sub New(ByVal text As String, ByVal checkedOut As Date)
            MyBase.New(text)
            _CheckedOut = checkedOut
        End Sub 

        Public ReadOnly Property CheckedOut() As Date 
            Get 
                Return _CheckedOut
            End Get 
        End Property 

    End Class 
End Namespace
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; }
        }
    }
}
using namespace System;
using namespace System::Security::Permissions;
using namespace System::Runtime::Serialization;

namespace Samples1 
{
    // Violates this rule
    [Serializable]
    public ref class Book : ISerializable
    {
    private:
        initonly String^ _Title;

    public: 
        Book(String^ title)
        {
            if (title == nullptr)
                throw gcnew ArgumentNullException("title");

            _Title = title;
        }

        property String^ Title
        {
            String^ get()
            {
                return _Title;
            }
        }

    protected: 
        Book(SerializationInfo^ info, StreamingContext context)
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            _Title = info->GetString("Title");
        }

    private:
        [SecurityPermission(SecurityAction::LinkDemand, Flags = SecurityPermissionFlag::SerializationFormatter)]
        void virtual GetObjectData(SerializationInfo^ info, StreamingContext context) sealed = ISerializable::GetObjectData
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            info->AddValue("Title", _Title);
        }
    };

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

    public:
        LibraryBook(String^ title, DateTime checkedOut) : Book(title)
        {
            _CheckedOut = checkedOut;
        }

        property DateTime CheckedOut
        {
            DateTime get()
            {
                return _CheckedOut;
            }
        }
    };
}

Im folgenden Beispiel werden die zwei zuvor dargestellten Verstöße korrigiert, indem eine überschreibbare Implementierung von [ISerializable.GetObjectData] in der Book-Klasse und eine Implementierung von [ISerializable.GetObjectData] in der Library-Klasse bereitgestellt werden.

Imports System
Imports System.Security.Permissions
Imports System.Runtime.Serialization

Namespace Samples2

    <Serializable()> _
    Public Class Book
        Implements ISerializable

        Private ReadOnly _Title As String 

        Public Sub New(ByVal title As String)
            If (title Is Nothing) Then Throw New ArgumentNullException("title")
            _Title = title
        End Sub 

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            _Title = info.GetString("Title")
        End Sub 

        Public ReadOnly Property Title() As String 
            Get 
                Return _Title
            End Get 
        End Property

        <SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Protected Overridable Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) _
            Implements ISerializable.GetObjectData

            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            info.AddValue("Title", _Title)
        End Sub 
    End Class


    <Serializable()> _
    Public Class LibraryBook
        Inherits Book

        Private ReadOnly _CheckedOut As Date 

        Public Sub New(ByVal text As String, ByVal checkedOut As Date)
            MyBase.New(text)
            _CheckedOut = checkedOut
        End Sub 

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            MyBase.New(info, context)

            _CheckedOut = info.GetDateTime("CheckedOut")
        End Sub 

        Public ReadOnly Property CheckedOut() As Date 
            Get 
                Return _CheckedOut
            End Get 
        End Property

        <SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Protected Overrides Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, _
                                              ByVal context As System.Runtime.Serialization.StreamingContext)

            MyBase.GetObjectData(info, context)

            info.AddValue("CheckedOut", _CheckedOut)
        End Sub 
    End Class 
End Namespace
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);
        }
    }
}
using namespace System;
using namespace System::Security::Permissions;
using namespace System::Runtime::Serialization;

namespace Samples2 
{
    [Serializable]
    public ref class Book : ISerializable
    {
    private:
        initonly String^ _Title;

    public: 
        Book(String^ title)
        {
            if (title == nullptr)
                throw gcnew ArgumentNullException("title");

            _Title = title;
        }

        property String^ Title
        {
            String^ get()
            {
                return _Title;
            }
        }

    protected: 
        Book(SerializationInfo^ info, StreamingContext context)
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            _Title = info->GetString("Title");
        }

        [SecurityPermission(SecurityAction::LinkDemand, Flags = SecurityPermissionFlag::SerializationFormatter)]
        void virtual GetObjectData(SerializationInfo^ info, StreamingContext context) = ISerializable::GetObjectData
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            info->AddValue("Title", _Title);
        }
    };

    [Serializable]
    public ref class LibraryBook : Book
    {
        initonly DateTime _CheckedOut;

    public:
        LibraryBook(String^ title, DateTime checkedOut) 
            : Book(title)
        {
            _CheckedOut = checkedOut;
        }

        property DateTime CheckedOut
        {
            DateTime get()
            {
                return _CheckedOut;
            }
        }

    protected: 
        LibraryBook(SerializationInfo^ info, StreamingContext context) : Book(info, context)
        {
            _CheckedOut = info->GetDateTime("CheckedOut");
        }

        [SecurityPermission(SecurityAction::LinkDemand, Flags = SecurityPermissionFlag::SerializationFormatter)]
        void virtual GetObjectData(SerializationInfo^ info, StreamingContext context) override
        {
            Book::GetObjectData(info, context);
            info->AddValue("CheckedOut", _CheckedOut);
        }
    };
}

Verwandte Regeln

CA2236: Basisklassenmethoden auf ISerializable-Typen aufrufen

CA2229: Serialisierungskonstruktoren implementieren

CA2238: Serialisierungsmethoden korrekt implementieren

CA2235: Alle nicht serialisierbaren Felder markieren

CA2237: Markieren von ISerializable-Typen mit SerializableAttribute

CA2239: Deserialisierungsmethoden für optionale Felder angeben

CA2120: Sichere Serialisierungskonstruktoren