CA2240: Implementar ISerializable corretamente
Item | Valor |
---|---|
RuleId | CA2240 |
Categoria | Microsoft.Usage |
Alteração da falha | Sem interrupção |
Causa
Um tipo visível externamente pode ser atribuído à interface System.Runtime.Serialization.ISerializable e uma das seguintes condições é verdadeira:
O tipo herda, mas não substitui o método System.Runtime.Serialization.ISerializable.GetObjectData e o tipo declara campos de instância que não estão marcados com o atributo System.NonSerializedAttribute.
O tipo não é selado e o tipo implementa um método GetObjectData que não é substituível e visível externamente.
Descrição da regra
Os campos de instância declarados em um tipo que herda a interface System.Runtime.Serialization.ISerializable não são incluídos automaticamente no processo de serialização. Para incluir os campos, o tipo deve implementar o método GetObjectData e o construtor de serialização. Se os campos não devem ser serializados, aplique o atributo NonSerializedAttribute aos campos para indicar explicitamente a decisão.
Em tipos que não são selados, as implementações do método GetObjectData devem ser visíveis externamente. Portanto, o método pode ser chamado por tipos derivados e é substituível.
Como corrigir violações
Para corrigir uma violação dessa regra, deixe o método GetObjectData visível e substituível e verifique se todos os campos de instância estão incluídos no processo de serialização ou marcados explicitamente com o atributo NonSerializedAttribute.
Quando suprimir avisos
Não suprima um aviso nessa regra.
Exemplo 1
O exemplo a seguir mostra dois tipos serializáveis que violam a regra.
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; }
}
}
}
Exemplo 2
O exemplo a seguir corrige as duas violações anteriores fornecendo uma implementação substituível de GetObjectData na classe Book e fornecendo uma implementação de GetObjectData
na 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);
}
}
}
Regras relacionadas
- CA2236: Chamar métodos da classe base em tipos ISerializable
- CA2229: Implementar construtores de serialização
- CA2238: Implementar métodos de serialização corretamente
- CA2235: Marcar todos os campos não serializáveis
- CA2237: Marcar tipos ISerializable com SerializableAttribute
- CA2239: Fornecer métodos de desserialização para campos opcionais
- CA2120: Construtores de serialização seguros
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de