2009-05-05 8 views
4

Dans une question précédente sur serialising an object to an XmlDocument in C#, je devais sérialiser certaines informations de panne à un XmlDocument qui a été renvoyé à partir d'un appel de service Web de style asmx. Sur le client, j'ai besoin de désérialiser le XmlDocument retour à un objet.Sérialiser en XML et inclure le type de l'objet sérialisé

C'est assez simple si vous connaissez le type, mais j'ai réalisé que je voulais une approche flexible où le type à désérialiser est également codé dans le XmlDocument. Je fais actuellement manuellement en ajoutant un XmlNode au XmlDocument qui a le nom du type, calculé comme suit:

Type type = fault.GetType(); 
    string assemblyName = type.Assembly.FullName; 

    // Strip off the version and culture info 
    assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(",")).Trim(); 

    string typeName = type.FullName + ", " + assemblyName; 

Puis sur le client, j'obtiens d'abord ce nom de type retour de la XmlDocument, et créer le type objet qui est passé dans le XmlSerialiser ainsi:

 object fault; 
     XmlNode faultNode = e.Detail.FirstChild; 
     XmlNode faultTypeNode = faultNode.NextSibling; 

     // The typename of the fault type is the inner xml of the first node 
     string typeName = faultTypeNode.InnerXml; 
     Type faultType = Type.GetType(typeName); 

     // The serialised data for the fault is the second node 
     using (var stream = new StringReader(faultNode.OuterXml)) 
     { 
      var serialiser = new XmlSerializer(faultType); 
      objectThatWasSerialised = serialiser.Deserialize(stream); 
     } 

     return (CastToType)fault; 

C'est donc une approche force brute, et je me demandais s'il y a une solution plus élégante qui comprend en quelque sorte le typename du type sérialisé automatiquement, au lieu d'enregistrer manuellement ailleurs ailleurs?

Répondre

3

J'avais rencontré un problème similaire et j'ai trouvé la même solution. En ce qui me concerne, c'est le seul moyen de garder les types avec les valeurs dans la sérialisation XML.

Je vois que vous découpez la version d'assemblage comme je l'ai fait aussi. Mais je voudrais mentionner, que vous aurez des problèmes avec des types génériques que leur signature ressemble à ce que:

System.Nullable`1[[System.Int, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 

donc j'ai fait fonction seulement découper la version de montage (s), qui semble être assez pour se débarrasser des problèmes de versioning:

private static string CutOutVersionNumbers(string fullTypeName) 
    { 
     string shortTypeName = fullTypeName; 
     var versionIndex = shortTypeName.IndexOf("Version"); 
     while (versionIndex != -1) 
     { 
      int commaIndex = shortTypeName.IndexOf(",", versionIndex); 
      shortTypeName = shortTypeName.Remove(versionIndex, commaIndex - versionIndex + 1); 
      versionIndex = shortTypeName.IndexOf("Version"); 
     } 
     return shortTypeName; 
    } 
+0

+1 pour fournir un bon code de copie/collage et rendre ma vie un peu plus facile. – Phil

0

Neil, pourquoi avez-vous besoin qu'il soit le le même type sur le client et le serveur?

Utilisez-vous encore ASMX sur le client? Ce serait une raison, ASMX ne supporte pas correctement les fautes.

De même, avez-vous tellement de types de défauts différents qu'un simple commutateur instruction ne peut pas déterminer le type correct à utiliser?

+0

J'utilise asmx sur le serveur et le client, oui. Je suis en train de mettre en place une sorte de système de failles de type WCF à moitié cuit parce que sur le client j'utilise une interface pour le service asmx et je ne veux pas que les utilisateurs de cette interface obtiennent SoapExceptions, donc ils obtiennent quelque chose J'ai appelé une exception ServiceException, avec une propriété Fault. Cette propriété fault est renvoyée au client asmx dans la propriété SoapException.Detail, d'où la sérialisation XmlDocument/XmlNode. Je n'ai pas beaucoup de types de défauts pour le moment, mais je veux de la flexibilité pour ajouter plus au serveur sans casser les clients déployés. –

+1

Donc, vous ne réinventez pas la roue; vous réinventez la WCF. –

Questions connexes