CA2240: Implementar ISerializable correctamente
Elemento | Valor |
---|---|
RuleId | CA2240 |
Category | Microsoft.Usage |
Cambio importante | Poco problemático |
Causa
Se puede asignar un tipo visible externamente a la interfaz System.Runtime.Serialization.ISerializable y se cumple una de las condiciones siguientes:
El tipo hereda pero no invalida el método System.Runtime.Serialization.ISerializable.GetObjectData y el tipo declara campos de instancia que no están marcados con el atributo System.NonSerializedAttribute.
El tipo no está sellado y el tipo implementa un método GetObjectData que no es visible externamente y reemplazable.
Descripción de la regla
Los campos de instancia declarados en un tipo que hereda la interfaz System.Runtime.Serialization.ISerializable no se incluyen automáticamente en el proceso de serialización. Para incluir los campos, el tipo debe implementar el método GetObjectData y el constructor de serialización. Si los campos no se deben serializar, aplique el atributo NonSerializedAttribute a los campos para indicar explícitamente la decisión.
En los tipos que no están sellados, las implementaciones del método GetObjectData deben estar visibles externamente. Por lo tanto, los tipos derivados pueden llamar al método, y este se puede invalidar.
Cómo corregir infracciones
Para corregir una infracción de esta regla, haga que el método GetObjectData sea visible y reemplazable, y asegúrese de que todos los campos de instancia se incluyan en el proceso de serialización o se marquen explícitamente con el atributo NonSerializedAttribute.
Cuándo suprimir las advertencias
No suprima las advertencias de esta regla.
Ejemplo 1
En el ejemplo siguiente se muestran dos tipos serializables que infringen la regla.
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; }
}
}
}
Ejemplo 2
En el ejemplo siguiente se corrigen las dos infracciones anteriores al proporcionar una implementación reemplazable de GetObjectData en la clase Book y una implementación de GetObjectData
en la clase 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);
}
}
}
Reglas relacionadas
- CA2236: Llamar a métodos de clase base en tipos ISerializable
- CA2229: Implementar constructores de serialización
- CA2238: Implementar métodos de serialización correctamente
- CA2235: Marcar todos los campos no serializables
- CA2237: Marcar los tipos ISerializable con SerializableAttribute
- CA2239: Proporcionar métodos de deserialización para campos opcionales
- CA2120: Proteger los constructores de serializaciones
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de