Vlastní serializace

Vlastní serializace je proces řízení serializace a deserializace typu. Kontrolou serializace je možné zajistit kompatibilitu serializace, což je schopnost serializovat a deserializovat mezi verzemi typu bez porušení základních funkcí typu. Například v první verzi typu, může existovat pouze dvě pole. V příští verzi typu jsou přidány několik více polí. Ještě druhý verze aplikace, musí mít k serializaci a deserializaci oba typy. Níže uvedené části popisují, jak řídit serializace.

Upozornění

Binární serializace může být nebezpečná. Další informace najdete v průvodci zabezpečením BinaryFormatter.

Důležité

Ve verzích předchozích .NET Framework 4.0 bylo serializace vlastních uživatelských dat v částečně důvěryhodném sestavení provedena pomocí GetObjectData. V .NET Framework verze 4.0 – 4.8 je tato metoda označena atributemSecurityCriticalAttribute, který brání provádění v částečně důvěryhodných sestaveních. Chcete-li vyřešit tuto podmínku, implementovat ISafeSerializationData rozhraní.

Spouštění vlastních metod během serializace a po serializaci

Doporučeným způsobem spuštění vlastních metod během serializace a po serializaci je použití následujících atributů na metody, které se používají k opravě dat během a po serializaci:

Tyto atributy umožňují typ k účasti v jedné z nebo všechny čtyři fází procesů serializace a deserializace. Atributy určují metody typu, který má být volána v každé fázi. Metody není přístup k datový proud serializace, ale místo toho bylo možné změnit objekt před a po serializaci, nebo před a po deserializace. Atributy lze použít na všech úrovních hierarchie dědičnosti typů a každá metoda je volána v hierarchii z základní k nejvíce odvozené. Tento mechanismus zabraňuje složitost a všechny výsledné problémy provádění ISerializable rozhraní tím, že odpovědnost za serializace a deserializace za účelem implementace Většina odvozených. Kromě toho tento mechanismus umožňuje formátovací moduly, ignorovat naplnění polí a načtení z datový proud serializace. Podrobnosti a příklady řízení serializace a deserializace klikněte na tlačítko Předchozí odkazy.

Kromě toho při přidávání nového pole na existující serializovatelný typ., použije OptionalFieldAttribute atributu na pole. BinaryFormatter a SoapFormatter ignoruje absenci pole při zpracování datový proud, který chybí nové pole.

Implementace rozhraní ISerializable

Druhý způsob, jak řídit serializaci, je dosaženo implementací ISerializable rozhraní na objektu. Upozorňujeme však, že metoda v předchozím oddílu nahrazuje tuto metodu za účelem serializace ovládacího prvku.

Kromě toho byste neměli používat výchozí serializaci třídy, která je označena serializable atribut a má deklarativní nebo imperativní zabezpečení na úrovni třídy nebo na jeho konstruktory. Namísto toho měli vždy implementovat tyto třídy ISerializable rozhraní.

Implementace ISerializable zahrnuje implementaci GetObjectData metody a speciálního konstruktoru, který se používá při deserializaci objektu. Následující ukázkový kód ukazuje, jak implementovat ISerializable na MyObject třídy z předchozího oddílu.

[Serializable]
public class MyObject : ISerializable
{
    public int n1;
    public int n2;
    public String str;

    public MyObject()
    {
    }

    protected MyObject(SerializationInfo info, StreamingContext context)
    {
      n1 = info.GetInt32("i");
      n2 = info.GetInt32("j");
      str = info.GetString("k");
    }

    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("i", n1);
        info.AddValue("j", n2);
        info.AddValue("k", str);
    }
}
<Serializable()>  _
Public Class MyObject
    Implements ISerializable
    Public n1 As Integer
    Public n2 As Integer
    Public str As String

    Public Sub New()
    End Sub

    Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
        n1 = info.GetInt32("i")
        n2 = info.GetInt32("j")
        str = info.GetString("k")
    End Sub 'New

    Public Overridable Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext)
        info.AddValue("i", n1)
        info.AddValue("j", n2)
        info.AddValue("k", str)
    End Sub
End Class

Při volání GetObjectData během serializace zodpovídáte za naplnění SerializationInfo zadaného volání metody. Přidáte proměnné mají být serializován jako dvojice název a hodnotu. Libovolný text, lze použít jako název. Máte svobodu rozhodnutí, které členské proměnné jsou přidány do SerializationInfo, za předpokladu, že serializován dostatek dat. Chcete-li obnovit během deserializace objektu. Odvozené třídy by měly volat GetObjectData metoda na základní objekt, pokud druhá implementuje ISerializable.

Je důležité zdůraznit, že při ISerializable přidání do třídy je nutné implementovat GetObjectData i speciální konstruktor. Kompilátor vás upozorní, pokud chybí GetObjectData . Protože je nelze vynutit provádění konstruktor, bez upozornění je však k dispozici pokud chybí konstruktor a je vyvolána výjimka, pokud je proveden pokus o deserializaci třídy bez konstruktoru.

Aktuální návrh byl podporuje výše SetObjectData metodu za účelem získání kolem potenciální problémy zabezpečení a správy verzí. Například metoda musí být veřejná, pokud je definována jako součást rozhraní. Uživatelé proto musí psát kód, který se má bránit proti tomu, SetObjectData aby byla metoda SetObjectData volána vícekrát. V opačném případě může škodlivá aplikace, která volá SetObjectData metodu objektu v procesu provádění operace způsobit potenciální problémy.

Během deserializace SerializationInfo je předán do třídy pomocí konstruktoru určených k tomuto účelu. Omezeními viditelnost umístí na konstruktoru jsou ignorovány, pokud je objekt deserializován; Třída tak můžete označit jako veřejné, chráněný, interní nebo privátní. Je však osvědčeným postupem zajistit konstruktoru chráněný, pokud zapečetěné třídy v takovém případě by měla být konstruktoru označena privátní. Konstruktor by měl také provést důkladné ověření vstupu.

Chcete-li obnovit stav objektu, jednoduše načíst hodnoty proměnných z SerializationInfo pomocí názvů používat během serializace. Pokud je základní třída implementuje ISerializable, by měla být volána konstruktor základní třídy, aby umožnila základní objekt, který chcete obnovit své proměnné.

Když odvozujete novou třídu z té, která implementuje ISerializable, odvozená třída musí implementovat konstruktor i GetObjectData metoda, pokud má proměnné, které je potřeba serializovat. Následující příklad kódu ukazuje, jak to lze provést pomocí MyObject třídy, které jsou uvedeny dříve.

[Serializable]
public class ObjectTwo : MyObject
{
    public int num;

    public ObjectTwo()
      : base()
    {
    }

    protected ObjectTwo(SerializationInfo si, StreamingContext context)
      : base(si, context)
    {
        num = si.GetInt32("num");
    }

    public override void GetObjectData(SerializationInfo si, StreamingContext context)
    {
        base.GetObjectData(si,context);
        si.AddValue("num", num);
    }
}
<Serializable()>  _
Public Class ObjectTwo
    Inherits MyObject
    Public num As Integer

    Public Sub New()

    End Sub

    Protected Sub New(ByVal si As SerializationInfo, _
    ByVal context As StreamingContext)
        MyBase.New(si, context)
        num = si.GetInt32("num")
    End Sub

    Public Overrides Sub GetObjectData(ByVal si As SerializationInfo, ByVal context As StreamingContext)
        MyBase.GetObjectData(si, context)
        si.AddValue("num", num)
    End Sub
End Class

Nezapomeňte volat základní třídu v konstruktoru deserializace. Pokud to není hotové, konstruktor základní třídy se nikdy nevolá a objekt není po deserializaci plně vytvořen.

Objekty jsou znovu vytvořena zevnitř a volání metod během deserializace může mít nežádoucí vedlejší účinky, protože volání metody může odkazovat na objekt odkazy, které nebyly byla deserializovat o dobu, kterou při volání. Pokud třída deserializovaná implementuje IDeserializationCallback, OnDeserialization metoda se automaticky volá, když byl deserializován celý objektový graf. V tomto okamžiku byly plně obnoveny všechny podřízené objekty odkazuje. Tabulka hash je typickým příkladem třídu, která je obtížné deserializaci bez použití naslouchací proces události. Vše je snadné k načtení dvojice klíč a hodnotu během deserializace, ale přidáním těchto objektů zpět do tabulky algoritmu hash může způsobit problémy vzhledem k tomu, že neexistuje žádná záruka této třídy, které odvozen z tabulky hash deserializovat. Volání metod z tabulky hash v této fázi není proto doporučuje.

Viz také