Udostępnij za pośrednictwem


BinaryFormatter dokumentacja funkcji

Element BinaryFormatter został wprowadzony po raz pierwszy w wersji początkowej programu .NET Framework w 2002 roku. Aby zrozumieć, jak zastąpić użycie elementu BinaryFormatter, pomaga wiedzieć, jak BinaryFormatter działa.

BinaryFormatter program może serializować dowolne wystąpienie dowolnego typu, które jest oznaczone adnotacją lub [Serializable] implementuje ISerializable interfejs.

Nazwy elementów członkowskich

W najbardziej typowym scenariuszu typ jest oznaczony adnotacją [Serializable] , a serializator używa odbicia w celu serializacji wszystkich pól (zarówno publicznych, jak i niepublizowanych), z wyjątkiem tych, które są oznaczone [NonSerialized]jako . Domyślnie serializowane nazwy składowych będą zgodne z nazwami pól typu. To historycznie doprowadziło do niezgodności, gdy nawet prywatne pola są zmieniane na [Serializable] typy. Podczas migracji z dala od BinaryFormatterprogramu należy zrozumieć, jak serializowane nazwy pól były obsługiwane i zastępowane.

Właściwości automatyczne języka C#

W przypadku właściwości zaimplementowanych automatycznie w języku C# ({ get; set; }) BinaryFormatter program serializuje pola kopii zapasowej generowane przez kompilator języka C#, a nie właściwości. Nazwy tych serializowanych pól kopii zapasowych zawierają niedozwolone znaki języka C# i nie mogą być kontrolowane. Dekompiler języka C# (np https://sharplab.io/ . lub ILSpy) może zademonstrować sposób prezentowania właściwości automatycznych języka C# środowisku uruchomieniowemu.

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

Poprzednia klasa jest tłumaczona przez kompilator języka C#na:

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

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

W tym przypadku jest to nazwa elementu członkowskiego, <Name>k__BackingField który BinaryFormatter jest używany w serializowanym ładunku. Nie można użyć nameof ani żadnego innego operatora języka C#, aby uzyskać tę nazwę.

Interfejs ISerializable zawiera GetObjectData metodę, która umożliwia użytkownikom kontrolowanie nazw przy użyciu jednej z AddValue metod.

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

Jeśli takie dostosowanie zostało zastosowane, należy również podać informacje podczas deserializacji. Jest to możliwe przy użyciu konstruktoraserialization, w którym wszystkie wartości są odczytywane z SerializationInfo jednej z Get metod, które zapewnia.

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

Uwaga

Operator nameof nie był celowo używany w tym miejscu, ponieważ można utrwały ładunek i właściwość może zostać zmieniona w późniejszym czasie. Więc nawet jeśli zostanie zmieniona (powiedzmy, FirstName ponieważ zdecydujesz się również wprowadzić LastName właściwość), aby zachować zgodność z poprzednimi wersjami, nadal powinna używać starej nazwy, serialization która mogła być utrwalone gdzieś.

Serialization spoiwo

Zaleca się sterowanie SerializationBinder ładowaniem klas i nakazywaniem ładowania klas. Minimalizuje to luki w zabezpieczeniach (dlatego dozwolone typy są ładowane, nawet jeśli osoba atakująca modyfikuje ładunek w celu deserializacji i załadowania czegoś innego).

Użycie tego typu wymaga dziedziczenia po nim i przesłaniania BindToType metody.

W idealnym przypadku lista typów możliwych do serializacji jest zamknięta, ponieważ oznacza to, że wiesz, które typy mogą zostać utworzone, co pomoże zmniejszyć luki w zabezpieczeniach.