Dela via


BinaryFormatter funktionsreferens

Den BinaryFormatter första introducerades med den första versionen av .NET Framework 2002. Om du vill förstå hur du ersätter användningen av BinaryFormatterhjälper det dig att veta hur BinaryFormatter det fungerar.

BinaryFormatter kan serialisera alla instanser av alla typer som kommenteras med [Serializable] eller implementerar ISerializable gränssnittet.

Medlemsnamn

I det vanligaste scenariot kommenteras typen med [Serializable] och serialiseraren använder reflektion för att serialisera alla fält (både offentliga och icke-offentliga) förutom de som kommenteras med [NonSerialized]. Som standard matchar de serialiserade medlemsnamnen typens fältnamn. Detta ledde historiskt till inkompatibiliteter när även privata fält byter namn på [Serializable] typer. Under migreringar bort från BinaryFormatterblir det nödvändigt att förstå hur serialiserade fältnamn hanterades och åsidosatts.

Autoegenskaper för C#

För C# -automatiskt implementerade egenskaper ({ get; set; }) BinaryFormatter serialiserar de bakgrundsfält som genereras av C#-kompilatorn, inte egenskaperna. Namnen på dessa serialiserade bakgrundsfält innehåller ogiltiga C#-tecken och kan inte styras. En C#-decompiler (till exempel https://sharplab.io/ eller ILSpy) kan visa hur C#-autoegenskaper visas för körningen.

[Serializable]
internal class PropertySample
{
    public string Name { get; set; }
}

Föregående klass översätts av C#-kompilatorn till:

[Serializable]
internal class PropertySample
{
    private string <Name>k__BackingField;

    public string Name
    {
        get
        {
            return <Name>k__BackingField;
        }
        set
        {
            <Name>k__BackingField = value;
        }
    }
}

I det här fallet <Name>k__BackingField är namnet på medlemmen som BinaryFormatter använder i den serialiserade nyttolasten. Det går inte att använda nameof eller någon annan C#-operator för att hämta det här namnet.

Gränssnittet ISerializable levereras med GetObjectData en metod som gör det möjligt för användarna att kontrollera namnen med hjälp av någon av AddValue metoderna.

// Note lack of any special attribute.
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("Name", this.Name);
}

Om sådan anpassning har tillämpats måste informationen också tillhandahållas under deserialiseringen. Det är möjligt med hjälp serialization av konstruktorn, där alla värden läse från SerializationInfo med någon av de metoder som Get den tillhandahåller.

private PropertySample(SerializationInfo info, StreamingContext context)
{
    this.Name = info.GetString("Name");
}

Kommentar

Operatorn nameof användes avsiktligt inte här eftersom nyttolasten kan sparas och egenskapen kan byta namn vid ett senare tillfälle. Så även om den byter namn (till exempel för att FirstName du bestämmer dig för att även införa en LastName egenskap), för att förbli bakåtkompatibel, serialization bör du fortfarande använda det gamla namnet som kunde ha sparats någonstans.

Serialization mapp

Vi rekommenderar att du använder SerializationBinder för att styra klassinläsning och kräva vilken klass som ska läsas in. Det minimerar säkerhetsrisker (så att endast tillåtna typer läses in, även om angriparen ändrar nyttolasten för att deserialisera och läsa in något annat).

Om du använder den här typen måste du ärva från den BindToType och åsidosätta metoden.

Helst är listan över serialiserbara typer stängd eftersom det innebär att du vet vilka typer som kan instansieras, vilket bidrar till att minska säkerhetsrisker.