Origine evento BinaryFormatter

A partire da .NET 5, BinaryFormatter include una funzionalità predefinita EventSource che offre visibilità in caso di serializzazione o deserializzazione di oggetti. Le app possono usare EventListenertipi derivati per ascoltare queste notifiche e registrarle.

Questa funzionalità non è una sostituzione di un SerializationBinder oggetto o di ISerializationSurrogate e non può essere usata per modificare i dati serializzati o deserializzati. Invece, questo sistema di eventi è destinato a fornire informazioni dettagliate sui tipi serializzati o deserializzati. Può essere usato anche per rilevare chiamate non intenzionali nell'infrastruttura BinaryFormatter , ad esempio le chiamate provenienti dal codice della libreria di terze parti.

Descrizione degli eventi

L'origine BinaryFormatter evento ha il nome System.Runtime.Serialization.Formatters.Binary.BinaryFormatterEventSourcenoto . I listener possono sottoscrivere sei eventi.

Evento SerializationStart (id = 10)

Generato quando BinaryFormatter.Serialize è stato chiamato e ha avviato il processo di serializzazione. Questo evento viene associato all'evento SerializationEnd . L'evento SerializationStart può essere chiamato ricorsivamente se un oggetto chiama BinaryFormatter.Serialize all'interno della propria routine di serializzazione.

Questo evento non contiene un payload.

Evento SerializationEnd (id = 11)

Generato al BinaryFormatter.Serialize termine del suo lavoro. Ogni occorrenza di SerializationEnd indica il completamento dell'ultimo evento non abbinato SerializationStart .

Questo evento non contiene un payload.

Evento SerializingObject (id = 12)

Generato quando BinaryFormatter.Serialize si trova nel processo di serializzazione di un tipo non primitivo. Alcuni BinaryFormatter casi speciali dell'infrastruttura (ad esempio string e int) e non generano questo evento quando vengono rilevati questi tipi. Questo evento viene generato per i tipi definiti dall'utente e altri tipi che BinaryFormatter non comprendono in modo nativo.

Questo evento può essere generato zero o più volte tra SerializationStart e SerializationEnd eventi.

Questo evento contiene un payload con un argomento:

Evento DeserializationStart (id = 20)

Generato quando BinaryFormatter.Deserialize è stato chiamato ed è stato avviato il processo di deserializzazione. Questo evento viene associato all'evento DeserializationEnd . L'evento DeserializationStart può essere chiamato in modo ricorsivo se un oggetto chiama BinaryFormatter.Deserialize all'interno della propria routine di deserializzazione.

Questo evento non contiene un payload.

Evento DeserializationEnd (id = 21)

Generato al BinaryFormatter.Deserialize termine del suo lavoro. Ogni occorrenza di DeserializationEnd indica il completamento dell'ultimo evento non abbinato DeserializationStart .

Questo evento non contiene un payload.

Evento DeserializingObject (id = 22)

Generato quando BinaryFormatter.Deserialize si trova nel processo di deserializzazione di un tipo non primitivo. Alcuni BinaryFormatter casi speciali dell'infrastruttura (ad esempio string e int) e non generano questo evento quando vengono rilevati questi tipi. Questo evento viene generato per i tipi definiti dall'utente e altri tipi che BinaryFormatter non comprendono in modo nativo.

Questo evento può essere generato zero o più volte tra DeserializationStart e DeserializationEnd eventi.

Questo evento contiene un payload con un argomento.

[Avanzate] Sottoscrizione a un subset di notifiche

I listener che desiderano sottoscrivere solo un subset di notifiche possono scegliere quali parole chiave abilitare.

  • Serialization = (EventKeywords)1: genera gli SerializationStarteventi , SerializationEnde SerializingObject .
  • Deserialization = (EventKeywords)2: genera gli DeserializationStarteventi , DeserializationEnde DeserializingObject .

Se non vengono forniti filtri di parole chiave durante EventListener la registrazione, vengono generati tutti gli eventi.

Per altre informazioni, vedere System.Diagnostics.Tracing.EventKeywords.

Codice di esempio

Il codice seguente:

  • crea un EventListenertipo derivato che scrive in System.Console,
  • sottoscrive il listener a BinaryFormatter-generate notifiche,
  • serializza e deserializza un semplice grafico a oggetti usando BinaryFormatter, e
  • analizza gli eventi generati.
using System;
using System.Diagnostics.Tracing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace BinaryFormatterEventSample
{
    class Program
    {
        static EventListener? _globalListener = null;

        static void Main(string[] args)
        {
            // First, set up the event listener.
            // Note: We assign it to a static field so that it doesn't get GCed.
            // We also provide a callback that subscribes this listener to all
            // events produced by the well-known BinaryFormatter source.

            _globalListener = new ConsoleEventListener();
            _globalListener.EventSourceCreated += (sender, args) =>
            {
                if (args.EventSource?.Name ==
                    "System.Runtime.Serialization.Formatters.Binary.BinaryFormatterEventSource")
                {
                    ((EventListener?)sender)?
                        .EnableEvents(args.EventSource, EventLevel.LogAlways);
                }
            };

            // Next, create the Person object and serialize it.

            Person originalPerson = new Person()
            {
                FirstName = "Logan",
                LastName = "Edwards",
                FavoriteBook = new Book()
                {
                    Title = "A Tale of Two Cities",
                    Author = "Charles Dickens",
                    Price = 10.25m
                }
            };

            byte[] serializedPerson = SerializePerson(originalPerson);

            // Finally, deserialize the Person object.

            Person rehydratedPerson = DeserializePerson(serializedPerson);

            Console.WriteLine
                ($"Rehydrated person {rehydratedPerson.FirstName} {rehydratedPerson.LastName}");
            Console.Write
                ($"Favorite book: {rehydratedPerson.FavoriteBook?.Title} ");
            Console.Write
                ($"by {rehydratedPerson.FavoriteBook?.Author}, ");
            Console.WriteLine
                ($"list price {rehydratedPerson.FavoriteBook?.Price}");
        }

        private static byte[] SerializePerson(Person p)
        {
            MemoryStream memStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
#pragma warning disable SYSLIB0011 // BinaryFormatter.Serialize is obsolete
            formatter.Serialize(memStream, p);
#pragma warning restore SYSLIB0011

            return memStream.ToArray();
        }

        private static Person DeserializePerson(byte[] serializedData)
        {
            MemoryStream memStream = new MemoryStream(serializedData);
            BinaryFormatter formatter = new BinaryFormatter();

#pragma warning disable SYSLIB0011 // Danger: BinaryFormatter.Deserialize is insecure for untrusted input
            return (Person)formatter.Deserialize(memStream);
#pragma warning restore SYSLIB0011
        }
    }

    [Serializable]
    public class Person
    {
        public string? FirstName;
        public string? LastName;
        public Book? FavoriteBook;
    }

    [Serializable]
    public class Book
    {
        public string? Title;
        public string? Author;
        public decimal? Price;
    }

    // A sample EventListener that writes data to System.Console.
    public class ConsoleEventListener : EventListener
    {
        protected override void OnEventWritten(EventWrittenEventArgs eventData)
        {
            base.OnEventWritten(eventData);

            Console.WriteLine($"Event {eventData.EventName} (id={eventData.EventId}) received.");
            if (eventData.PayloadNames != null)
            {
                for (int i = 0; i < eventData.PayloadNames.Count; i++)
                {
                    Console.WriteLine($"{eventData.PayloadNames[i]} = {eventData.Payload?[i]}");
                }
            }
        }
    }
}

Il codice precedente produce output simile all'esempio seguente:

Event SerializationStart (id=10) received.
Event SerializingObject (id=12) received.
typeName = BinaryFormatterEventSample.Person, BinaryFormatterEventSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Event SerializingObject (id=12) received.
typeName = BinaryFormatterEventSample.Book, BinaryFormatterEventSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Event SerializationStop (id=11) received.
Event DeserializationStart (id=20) received.
Event DeserializingObject (id=22) received.
typeName = BinaryFormatterEventSample.Person, BinaryFormatterEventSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Event DeserializingObject (id=22) received.
typeName = BinaryFormatterEventSample.Book, BinaryFormatterEventSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Event DeserializationStop (id=21) received.
Rehydrated person Logan Edwards
Favorite book: A Tale of Two Cities by Charles Dickens, list price 10.25

In questo esempio, i log basati sulla EventListener console che avviano la serializzazione, le istanze di Person e Book vengono serializzate e quindi la serializzazione viene completata. Analogamente, una volta avviata la deserializzazione, le istanze di Person e Book vengono deserializzate e quindi la deserializzazione viene completata.

L'app stampa quindi i valori contenuti nell'oggetto deserializzato per dimostrare che l'oggetto ha serializzato Person e deserializzato correttamente.

Vedi anche

Per altre informazioni sull'uso EventListener per ricevere EventSourcenotifiche basate su dati, vedere la EventListener classe .