CA2240: ISerializable을 올바르게 구현하십시오.

항목
RuleId CA2240
범주 Microsoft.Usage
주요 변경 내용 주요 변경 아님

원인

외부에 표시되는 형식이 System.Runtime.Serialization.ISerializable 인터페이스에 할당 가능하며 다음 조건 중 하나에 해당합니다.

규칙 설명

System.Runtime.Serialization.ISerializable 인터페이스를 상속하는 형식에서 선언되는 인스턴스 필드는 serialization 프로세스에 자동으로 포함되지 않습니다. 필드를 포함하려면 형식은 GetObjectData 메서드와 serialization 생성자를 구현해야 합니다. 필드를 직렬화하지 않아야 하는 경우 NonSerializedAttribute 특성을 필드에 적용하여 결정을 명시적으로 표시합니다.

봉인되지 않은 형식에서는 GetObjectData 메서드의 구현은 외부에 표시되어야 합니다. 따라서 이 메서드는 파생 형식에 의해 호출될 수 있으며 재정의할 수 있습니다.

위반 문제를 해결하는 방법

이 규칙 위반 문제를 해결하려면 GetObjectData 메서드를 표시되고 재정의 가능하도록 설정하고 모든 인스턴스 필드가 serialization 프로세스에 포함되거나 NonSerializedAttribute 특성으로 명시적으로 표시되도록 합니다.

경고를 표시하지 않는 경우

이 규칙에서는 경고를 표시해야 합니다.

예 1

다음 예제에서는 규칙을 위반하는 두 가지 직렬화 가능 형식을 보여 줍니다.

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

예제 2

다음 예제에서는 Book 클래스에서 GetObjectData의 재정의 가능한 구현을 제공하고 Library 클래스에서 GetObjectData의 구현을 제공하여 두 가지 이전 위반 문제를 해결합니다.

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