Condividi tramite


CA2240: Implementare ISerializable in modo corretto

Articolo Valore
ID regola CA2240
Category Microsoft.Usage
Modifica Nessuna interruzione

Causa

Un tipo visibile esternamente è assegnabile all'interfaccia System.Runtime.Serialization.ISerializable e una delle condizioni seguenti è vera:

Descrizione regola

I campi dell'istanza dichiarati in un tipo che eredita l'interfaccia System.Runtime.Serialization.ISerializable non vengono inclusi automaticamente nel processo di serializzazione. Per includere i campi, il tipo deve implementare il GetObjectData metodo e il costruttore di serializzazione. Se i campi non devono essere serializzati, applicare l'attributo NonSerializedAttribute ai campi per indicare in modo esplicito la decisione.

Nei tipi non sealed, le implementazioni del GetObjectData metodo devono essere visibili esternamente. Di conseguenza, il metodo può essere chiamato dai tipi derivati ed è sottoposto a override.

Come correggere le violazioni

Per correggere una violazione di questa regola, rendere visibile e sostituibile il GetObjectData metodo e assicurarsi che tutti i campi dell'istanza siano inclusi nel processo di serializzazione o contrassegnati in modo esplicito con l'attributo NonSerializedAttribute .

Quando eliminare gli avvisi

Non escludere un avviso da questa regola.

Esempio 1

Nell'esempio seguente vengono illustrati due tipi serializzabili che violano la regola.

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

Esempio 2

Nell'esempio seguente vengono risolte le due violazioni precedenti fornendo un'implementazione sostituibile di GetObjectData nella classe Book e fornendo un'implementazione di GetObjectData nella classe Library.

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