Sdílet prostřednictvím


BinaryFormatter referenční informace o funkcích

Poprvé BinaryFormatter byla představena v počáteční verzi rozhraní .NET Framework v roce 2002. Abyste pochopili, jak nahradit používání BinaryFormatter, pomůže vám zjistit, jak BinaryFormatter funguje.

BinaryFormatter může serializovat libovolnou instanci libovolného typu, který je opatřen poznámkami [Serializable] nebo implementuje ISerializable rozhraní.

Jména členů

Ve většině běžných scénářů je typ opatřen poznámkami [Serializable] a serializátor používá reflexi k serializaci všech polí (veřejné i neveřejné) s výjimkou těch, které jsou opatřeny poznámkami [NonSerialized]. Ve výchozím nastavení budou serializované názvy členů odpovídat názvům polí typu. To v minulosti vedlo k nekompatibilitě, když se u typů přejmenovávají [Serializable] i soukromá pole. Během migrace mimo BinaryFormatterni je nutné pochopit, jak byly serializované názvy polí zpracovávány a přepsány.

Automatické vlastnosti jazyka C#

V případě jazyka C# automaticky implementovaných vlastností ({ get; set; }) BinaryFormatter serializuje zálohovaná pole generovaná kompilátorem jazyka C#, nikoli vlastnosti. Názvy těchto serializovaných záložních polí obsahují neplatné znaky jazyka C# a nelze je ovládat. Dekompiler jazyka C# (například https://sharplab.io/ILSpy) může demonstrovat, jak jsou automatické vlastnosti jazyka C# prezentovány modulu runtime.

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

Předchozí třída je přeložena kompilátorem jazyka C# na:

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

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

V tomto případě je název člena, <Name>k__BackingField který BinaryFormatter používá v serializované datové části. K získání tohoto názvu není možné použít nameof ani žádný jiný operátor jazyka C#.

Rozhraní ISerializable se dodává s GetObjectData metodou, která uživatelům umožňuje řídit jména pomocí jedné z AddValue metod.

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

Pokud je toto přizpůsobení použito, je třeba informace poskytnout také během deserializace. To je možné pomocí konstruktoru serializace , kde jsou všechny hodnoty čteny z SerializationInfo pomocí jedné z metod Get, které poskytuje.

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

Poznámka:

Operátor nameof se zde záměrně nepoužil, protože datovou část lze zachovat a vlastnost se může později přejmenovat. Takže i když se přejmenuje (řekněme FirstName, protože se rozhodnete také zavést LastName vlastnost), aby zůstala zpětně kompatibilní, serializace by stále měla používat starý název, který by mohl být někde zachován.

Serialization pořadač

Doporučuje se použít SerializationBinder k řízení načítání tříd a určení, jakou třídu se má načíst. Tím se minimalizují ohrožení zabezpečení (takže se načtou jenom povolené typy, i když útočník upraví datovou část tak, aby deserializoval a načetl něco jiného).

Použití tohoto typu vyžaduje dědění z něj a přepsání BindToType metody.

V ideálním případě je seznam serializovatelných typů uzavřen, protože to znamená, že víte, které typy lze vytvořit instance, což pomůže snížit ohrožení zabezpečení.