BinaryFormatter Naslaginformatie over functionaliteit
De BinaryFormatter eerste werd geïntroduceerd met de eerste release van .NET Framework in 2002. Als u wilt weten hoe u het gebruik BinaryFormattervervangt, helpt het om te weten hoe BinaryFormatter het werkt.
BinaryFormatter kan elk exemplaar van elk type dat is geannoteerd met [Serializable]
of implementeert de ISerializable interface serialiseren.
Ledennamen
In het meest voorkomende scenario wordt het type geannoteerd met [Serializable]
en de serializer gebruikt weerspiegeling om alle velden (zowel openbaar als niet-openbaar) te serialiseren , behalve de velden die zijn geannoteerd met [NonSerialized]
. Standaard komen de geserialiseerde lidnamen overeen met de veldnamen van het type. Dit heeft in het verleden geleid tot incompatibiliteit wanneer zelfs privévelden worden hernoemd op [Serializable]
typen. Tijdens migraties van buiten BinaryFormatter, is het noodzakelijk om te begrijpen hoe geserialiseerde veldnamen werden verwerkt en overschreven.
C#-eigenschappen voor automatisch
Voor C# automatisch geïmplementeerde eigenschappen ({ get; set; }
), BinaryFormatter serialiseert u de backingvelden die worden gegenereerd door de C#-compiler, niet de eigenschappen. De namen van deze geserialiseerde back-upvelden bevatten ongeldige C#-tekens en kunnen niet worden beheerd. Een C#-decompiler (zoals https://sharplab.io/ of ILSpy) kan laten zien hoe C# automatische eigenschappen worden gepresenteerd aan de runtime.
[Serializable]
internal class PropertySample
{
public string Name { get; set; }
}
De vorige klasse wordt door de C#-compiler vertaald naar:
[Serializable]
internal class PropertySample
{
private string <Name>k__BackingField;
public string Name
{
get
{
return <Name>k__BackingField;
}
set
{
<Name>k__BackingField = value;
}
}
}
In dit geval <Name>k__BackingField
is dit de naam van het lid dat BinaryFormatter
wordt gebruikt in de geserialiseerde nettolading. Het is niet mogelijk om of een andere C#-operator te gebruiken nameof
om deze naam op te halen.
De ISerializable interface wordt geleverd met GetObjectData een methode waarmee de gebruikers de namen kunnen beheren met behulp van een van de AddValue methoden.
// Note lack of any special attribute.
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", this.Name);
}
Als een dergelijke aanpassing is toegepast, moet de informatie ook worden verstrekt tijdens de deserialisatie. Dat is mogelijk met behulp van de serialization constructor, waarbij alle waarden worden gelezen SerializationInfo met een van de Get
methoden die het biedt.
private PropertySample(SerializationInfo info, StreamingContext context)
{
this.Name = info.GetString("Name");
}
Notitie
De nameof
operator is hier niet gebruikt, omdat de nettolading kan worden behouden en de eigenschap op een later tijdstip kan worden hernoemd. Dus zelfs als de naam ervan wordt gewijzigd (bijvoorbeeld FirstName
omdat u besluit ook een LastName
eigenschap te introduceren), om achterwaarts compatibel te blijven, moet de serialization oude naam nog steeds worden gebruikt die ergens kan zijn behouden.
Serialization bindmiddel
Het is raadzaam om te gebruiken SerializationBinder om het laden van klassen te beheren en te verplichten welke klasse moet worden geladen. Dit minimaliseert beveiligingsproblemen (zodat alleen toegestane typen worden geladen, zelfs als de aanvaller de nettolading wijzigt om iets anders te deserialiseren en laden).
Als u dit type gebruikt, moet u deze overnemen en de BindToType methode overschrijven.
Idealiter is de lijst met serialiseerbare typen gesloten, omdat u weet welke typen kunnen worden geïnstantieerd, waardoor beveiligingsproblemen worden verminderd.