Sdílet prostřednictvím


CA2240: Implementujte správně ISerializable

Zboží Hodnota
RuleId CA2240
Kategorie Microsoft.Usage
Změna způsobující chybu Nenarušující

Příčina

Externě viditelný typ je možné přiřadit rozhraní System.Runtime.Serialization.ISerializable a jedna z následujících podmínek je pravdivá:

Popis pravidla

Pole instance deklarovaná v typu, který dědí System.Runtime.Serialization.ISerializable rozhraní, nejsou automaticky zahrnuta do procesu serializace. Chcete-li zahrnout pole, typ musí implementovat metodu GetObjectData a serializace konstruktor. Pokud by pole neměla být serializována, použijte NonSerializedAttribute atribut na pole explicitně indikovat rozhodnutí.

U typů, které nejsou zapečetěné, by měly být implementace GetObjectData metody externě viditelné. Proto lze metodu volat odvozenými typy a je přepsána.

Jak opravit porušení

Chcete-li opravit porušení tohoto pravidla, zviditelněte a přepsat metodu GetObjectData a ujistěte se, že všechna pole instance jsou zahrnuta do procesu serializace nebo explicitně označena atributem NonSerializedAttribute .

Kdy potlačit upozornění

Nepotlačujte upozornění na toto pravidlo.

Příklad 1

Následující příklad ukazuje dva serializovatelné typy, které porušují pravidlo.

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; }
        }
    }
}

Příklad 2

Následující příklad opravuje dvě předchozí porušení tím, že poskytuje přepisovatelnou implementaci GetObjectData třídy Knihy a poskytnutím implementace GetObjectData třídy Knihovny.

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);
        }
    }
}