Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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 konstruktora serializacji , gdzie wszystkie wartości są odczytywane z SerializationInfo za pomocą jednej z metod Get zapewnianych.
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 nazwa (powiedzmy na FirstName, ponieważ zdecydujesz się również wprowadzić właściwość LastName), aby zachować zgodność z poprzednimi wersjami, serializacja powinna nadal używać starej nazwy, która mogła zostać gdzieś zapisana.
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.