Delen via


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.