Come posso aggiungere un vincolo di tipo a includere qualsiasi cosa, serializzabile in un metodo generico?

StackOverflow https://stackoverflow.com/questions/945495

Domanda

Il mio metodo generico deve serializzare l'oggetto passato, tuttavia solo insistendo sul fatto che implementa ISerializable non sembra funzionare.Per esempio, ho una struct tornato da un servizio web (contrassegnati con SerializableAttribute) che serializza xml bene, ma, come previsto, il compilatore C# si lamenta.

C'è un modo per controllare l'oggetto è serializzabile prima di tentare di serializzarlo, o, meglio ancora, un modo di usare il where parola chiave per controllare l'oggetto è adatto?

Ecco il mio metodo:

public static void Push<T>(string url, T message)
        where T : ISerializable
{
    string xml = SerializeMessage(message);

    // Send the message to Amazon SQS
    SendMessageRequest sendReq = new SendMessageRequest { QueueUrl = url, MessageBody = xml };
    AmazonSQSClient client = new AmazonSQSClient(S3User, S3Pass);
    client.SendMessage(sendReq);
}

E SerializeMessage:

private static string SerializeMessage<T>(T message)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
    using (StringWriter stringWriter = new StringWriter())
    {
        xmlSerializer.Serialize(stringWriter, message);
        return stringWriter.ToString();
    }
}

Se questo non è possibile, qual è il modo migliore per eseguire un controllo che un oggetto serializzabile in fase di esecuzione?

È stato utile?

Soluzione

Non si può fare questo completamente tramite vincoli generici, ma si può fare un paio di cose per aiutare:

1) Mettere il new () vincolo del tipo generico (per attivare la capacità di deserializzare e garantire la XmlSerializer non si lamenta per la mancanza di ctor default):

where T : new()

2) Nella prima riga della gestione della serializzazione metodo (o il costruttore o in qualsiasi altro luogo non c'è bisogno di ripetere più e più volte), è possibile eseguire questo controllo:

if( !typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)) ) )
    throw new InvalidOperationException("A serializable Type is required");

Naturalmente, c'è ancora la possibilità di eccezioni di runtime quando si tenta di serializzare un tipo, ma questo sarà coprire i problemi più evidenti.

Altri suggerimenti

Ho scritto una lunghezza articolo del blog su questo argomento che si possono trovare utili.Principalmente si va in la serializzazione binaria, ma i concetti sono applicabili alla maggior parte qualsiasi formato di serializzazione.

Il lungo e breve di esso è

  • Non c'è modo di aggiungere un vincolo generico affidabile
  • L'unico modo per verificare se un oggetto era serializable è per serializzare e vedere se l'operazione ha esito positivo

L'unico modo per sapere se un oggetto è serializzabile è quello di cercare di serializzare esso.

In realtà, si stava chiedendo come dire se un tipo "è serializzabile", ma la questione reale sarà rispetto agli oggetti. Alcune istanze di un tipo non possono essere serializzabile anche se il tipo è contrassegnato [Serializable]. Per esempio, cosa succede se l'istanza contiene riferimenti circolari?

Al posto di

XmlSerializer XMLSerializer = new XmlSerializer (typeof (T));

try

XmlSerializer XMLSerializer = new XmlSerializer (message.GetType ());

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top