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.