2009-06-03 8 views
31

Il mio metodo generico ha bisogno di serializzare l'oggetto passato ad esso, tuttavia, solo insistendo sul fatto che implementa ISerializable non sembra funzionare. Per esempio, ho una struct restituita da un servizio web (contrassegnato con SerializableAttribute) che serializza su xml bene, ma, come previsto, il compilatore C# si lamenta.Come posso aggiungere un vincolo di tipo per includere qualcosa serializzabile in un metodo generico?

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

Ecco il mio metodo integrale:

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?

risposta

32

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

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

where T : new() 

2) sulla prima riga del maneggiare la serializzazione metodo (o il costruttore o in qualsiasi altro luogo non c'è bisogno di ripeterla più e più volte), è possibile eseguire questo controllo:

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

+3

Questa risposta è errata, in quanto darà dei falsi positivi. typeof (T) valuta System.Runtime.Type, che è ISerializable, quindi valuterà sempre true. Usa questo invece ... se (! Typeof (T) .IsSerializable &&! (Typeof (ISerializable) .IsAssignableFrom (typeof (T)))) –

+2

Grazie - aggiornato per i posteri :) –

+1

Downvote rimosso per la modifica del vecchio post –

0

Invece di

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

provare

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

7

Ho scritto un articolo del blog su questo argomento che potresti trovare utile. Principalmente va nella serializzazione binaria ma i concetti sono applicabili alla maggior parte dei formati di serializzazione.

Il lungo e breve di esso è

  • Non v'è alcun modo per aggiungere un vincolo generico affidabile
  • L'unico modo per controllare e vedere se un oggetto era serializzabile è serializzare e vedere se l'operazione ha esito positivo
3

L'unico modo per sapere se un oggetto è serializzabile è provare a serializzarlo.

Infatti, stavi chiedendo come dire se un tipo "è serializzabile", ma la domanda effettiva sarà rispetto agli oggetti. Alcune istanze di un tipo potrebbero non essere serializzabili anche se il tipo è contrassegnato [Serializable]. Ad esempio, cosa succede se l'istanza contiene riferimenti circolari?

Problemi correlati