2009-06-03 4 views
31

Meine generische Methode muss das an sie übergebene Objekt serialisieren, beharrt aber nur darauf, dass es ISerializable implementiert scheint nicht zu funktionieren. Zum Beispiel habe ich eine Struktur von einem Web-Service zurückgegeben (mit SerializableAttribute markiert), die in XML seriell, aber, wie erwartet, beschwert sich der C# -Compiler.Wie kann ich eine Typbeschränkung hinzufügen, um etwas Serialisierbares in eine generische Methode einzufügen?

Gibt es eine Möglichkeit, das Objekt serialisierbar zu überprüfen, bevor Sie versuchen, es zu serialisieren, oder, noch besser, eine Möglichkeit, das Schlüsselwort where zu verwenden, um zu prüfen, ob das Objekt geeignet ist?

Hier ist meine volle Methode:

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); 
} 

Und 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(); 
    } 
} 

Wenn dies nicht möglich ist, was ist der beste Weg, um eine Prüfung durchzuführen, dass ein Objekt zur Laufzeit serializable ist?

Antwort

32

Sie können dies über generische Einschränkungen nicht vollständig, aber Sie können ein paar Dinge tun, um zu helfen:

1) Setzen Sie die new() Einschränkung für den generischen Typen (die Fähigkeit zu ermöglichen, deserialisieren und sicherzustellen, die XmlSerializer beschwert sich nicht über einen Mangel an Standard ctor):

where T : new() 

2) In der ersten Zeile Ihrer Methode Umgang mit der Serialisierung (oder Konstruktor oder sonstwo Sie müssen nicht wiederholen immer wieder), können Sie diese Prüfung durchführen:

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

Natürlich gibt es immer noch die Möglichkeit von Laufzeitausnahmen, wenn versucht wird, einen Typ zu serialisieren, aber dies deckt die offensichtlichsten Probleme ab.

+3

Diese Antwort ist falsch, da dies falsche positive Ergebnisse ergibt. typeof (T) wird zu System.Runtime.Type ausgewertet, was ISerializable ist, sodass es immer als wahr ausgewertet wird. Benutze das stattdessen ... if (! Typeof (T) .IsSerializable &&! (Typeof (ISerializable) .IsAssignableFrom (typeof (T)))) –

+2

Danke - aktualisiert für die Nachwelt :) –

+1

Downvote entfernt für die Bearbeitung der alten Post –

0

Statt

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

versuchen

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

7

Ich habe einen langen Blogartikel zu diesem Thema geschrieben, den Sie vielleicht hilfreich finden. Es geht hauptsächlich in binäre Serialisierung, aber die Konzepte sind für fast alle Serialisierungsformate anwendbar.

Die lange und kurze davon ist

  • Es gibt keine Art und Weise ist eine zuverlässige generische Einschränkung
  • Der einzige Weg, zu überprüfen und sehen, ob ein Objekt hinzufügen war serializable ist es zu serialisieren und zu sehen, ob der Vorgang erfolgreich ist
3

Die einzige Möglichkeit festzustellen, ob ein Objekt serialisierbar ist, besteht darin, es zu serialisieren.

In der Tat haben Sie gefragt, wie man sagt, ob ein Typ "serialisierbar" ist, aber die eigentliche Frage wird in Bezug auf Objekte sein. Einige Instanzen eines Typs können möglicherweise nicht serialisiert werden, selbst wenn der Typ [Serializable] markiert ist. Was passiert zum Beispiel, wenn die Instanz Zirkelverweise enthält?

Verwandte Themen