CA2240: ISerializable ordnungsgemäß implementieren.
Element | Wert |
---|---|
RuleId | CA2240 |
Category | Microsoft.Usage |
Unterbrechende Änderung | Nicht unterbrechend |
Ursache
Der Schnittstelle System.Runtime.Serialization.ISerializable kann ein extern sichtbarer Typ zugewiesen werden, und eine der folgenden Bedingungen ist erfüllt:
Der Typ erbt die Methode System.Runtime.Serialization.ISerializable.GetObjectData, überschreibt sie aber nicht, und der Typ deklariert Instanzfelder, die nicht mit dem Attribut System.NonSerializedAttribute gekennzeichnet sind.
Der Typ ist nicht versiegelt, und der Typ implementiert eine GetObjectData-Methode, die extern nicht sichtbar und überschreibbar ist.
Regelbeschreibung
Instanzfelder, die in einem Typ deklariert sind, der die Schnittstelle System.Runtime.Serialization.ISerializable erbt, werden nicht automatisch in den Serialisierungsprozess einbezogen. Zur Einbeziehung der Felder muss der Typ die Methode GetObjectData und den Serialisierungskonstruktor implementieren. Wenn die Felder nicht serialisiert werden sollen, wenden Sie das Attribut NonSerializedAttribute auf die Felder an, um dies ausdrücklich anzugeben.
In nicht versiegelten Typen sollten Implementierungen der GetObjectData-Methode extern sichtbar sein. Daher kann die Methode von abgeleiteten Typen aufgerufen werden und ist überschreibbar.
Behandeln von Verstößen
Um einen Verstoß gegen diese Regel zu beheben, legen Sie die GetObjectData-Methode als sichtbar und überschreibbar fest und stellen sicher, dass alle Instanzfelder in den Serialisierungsprozess einbezogen oder explizit mit dem NonSerializedAttribute-Attribut gekennzeichnet wurden.
Wann sollten Warnungen unterdrückt werden?
Unterdrücken Sie keine Warnung dieser Regel.
Beispiel 1
Das folgende Beispiel zeigt zwei serialisierbare Typen, die gegen diese Regel verstoßen.
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; }
}
}
}
Beispiel 2
Das folgende Beispiel behebt die zwei vorherigen Verstöße, indem eine überschreibbare Implementierung von GetObjectData in der Klasse „Book“ und eine Implementierung von GetObjectData
in der Klasse „Library“ bereitgestellt wird.
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);
}
}
}
Ähnliche Regeln
- CA2236: Basisklassenmethoden auf ISerializable-Typen aufrufen.
- CA2229: Serialisierungskonstruktoren implementieren.
- CA2238: Serialisierungsmethoden korrekt implementieren.
- CA2235: Alle nicht serialisierbaren Felder markieren.
- CA2237: ISerializable-Typen mit SerializableAttribute markieren.
- CA2239: Deserialisierungsmethoden für optionale Felder angeben.
- CA2120: Sichere Serialisierungskonstruktoren.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für