C# sérialisation Xml, de la collecte et de l'élément racine
Mon application sérialise les objets dans les cours d'eau.
Voici un échantillon de ce dont j'ai besoin :
<links>
<link href="/users" rel="users" />
<link href="/features" rel="features" />
</links>
Dans ce cas, l'objet est une collection de "liens" de l'objet.
-----------Première version
Au début, j'ai utilisé le DataContractSerializer, mais vous ne pouvez pas sérialiser les membres comme des attributs (source)
Voici l'objet :
[DataContract(Name="link")]
public class LinkV1
{
[DataMember(Name="href")]
public string Url { get; set; }
[DataMember(Name="rel")]
public string Relationship { get; set; }
}
Et voici le résultat :
<ArrayOflink xmlns:i="...." xmlns="...">
<link>
<href>/users</href>
<rel>users</rel>
</link>
<link>
<href>/features</href>
<rel>features</rel>
</link>
</ArrayOflink>
----------- Deuxième version
Ok, pas tranquille ce que je veux, alors j'ai essayé le classique XmlSerializer, mais... oh nooon, vous ne pouvez pas spécifier le nom de l'élément racine & des éléments de la collection si l'élément racine est une collection...
Voici le code :
[XmlRoot("link")]
public class LinkV2
{
[XmlAttribute("href")]
public string Url { get; set; }
[XmlAttribute("rel")]
public string Relationship { get; set; }
}
Voici le résultat :
<ArrayOfLinkV2>
<LinkV2 href="/users" rel="users" />
<LinkV2 href="/features" rel="features" />
<LinkV2 href="/features/user/{keyUser}" rel="featuresByUser" />
</ArrayOfLinkV2>
----------- Troisième version
à l'aide de XmlSerializer + un élément racine :
[XmlRoot("trick")]
public class TotallyUselessClass
{
[XmlArray("links"), XmlArrayItem("link")]
public List<LinkV2> Links { get; set; }
}
Et de son résultat :
<trick>
<links>
<link href="/users" rel="users" />
<link href="/features" rel="features" />
<link href="/features/user/{keyUser}" rel="featuresByUser" />
</links>
</trick>
Gentil, mais je ne veux pas que le nœud racine !!
Je veux que ma collection soit le nœud racine.
Voici les contraintes :
- le code de sérialisation est générique, il fonctionne avec quoi que ce soit sérialisable
- l'opération inverse (de la désérialisation) ont à travailler trop
- Je ne veux pas regex le résultat (je sérialiser directement dans un flux de sortie)
Quelles sont mes solutions :
- Codage mon propre XmlSerializer
- Truc XmlSerializer, quand il travaille avec une collection (j'ai essayé, d'avoir à trouver une XmlRootElement et plurialize à générer son propre attribut xmlrootattribute, mais qui provoque des problème lors de la désérialisation + le nom d'éléments conserve encore le nom de la classe)
Une idée ?
Vraiment ce qui me dérange dans cette question, c'est que ce que je veux semble être vraiment vraiment vraiment simple...
XSL tricher n'est pas une option, car le sérialiseur écrit directement dans un cours d'eau... et merci pour l' [MessageContract] plomb, j'ai appris quelque chose aujourd'hui ^^ cependant il est profondément liée à la WCF et ne permet pas de contrôler finement un simple Sérialisation XML (je me trompe peut-être, juste découvert l'attribut)
OriginalL'auteur Mose | 2012-08-02
Vous devez vous connecter pour publier un commentaire.
Ok, voici ma solution finale (espérons que cela aide quelqu'un), qui permet de sérialiser un simple tableau, une Liste<>, HashSet<>, ...
Pour y parvenir, nous aurons besoin de dire le sérialiseur ce nœud racine à utiliser, et il est le genre de difficile...
1) l'Utilisation de 'XmlType" sur l'objet sérialisable
2) le Code d'un "smart-root-détecteur-pour-collection "méthode", qui sera de retour un attribut xmlrootattribute
3) appuyez sur cette attribut xmlrootattribute dans le sérialiseur
Je vous ai dit que c'était difficile 😉
Pour améliorer cette situation, vous pouvez :
A) Créer un XmlTypeInCollectionAttribute pour spécifier une coutume nom de la racine (Si la base de la pluralisation ne correspond pas à votre besoin)
B) Si possible, de la mémoire cache de votre XmlSerializer (dans un Dictionnaire statique par exemple).
Dans mes tests, instanciating un XmlSerializer sans le XmlRootAttributes prend 3ms.
Si vous spécifiez un attribut xmlrootattribute, il faut compter environ 80 ms (Juste pour en avoir un personnalisé nœud racine de nom !)
OriginalL'auteur Mose
XmlSerializer devrait être en mesure de faire ce que vous avez besoin, mais il est très dépendant de la structure initiale et la configuration. Je l'utilise dans mon propre code pour générer remarquablement semblables choses.
maintenant, la sérialisation de l'
Links
classe devrait générer exactement ce que vous cherchez.Le problème avec XmlSerializer est lorsque vous donnez de génériques, il répond avec des génériques. Liste implemets Tableau quelque part là-bas et la sérialisé résultat sera presque toujours
ArrayOf<X>
. Pour obtenir autour de ce que vous pouvez nom de la propriété, ou de la classe racine. La ferme de ce que vous avez besoin est probablement la Deuxième Version de vos exemples. Im en supposant que vous avez tenté directe de la sérialisation d'un objet Liste de Liens. Qui ne fonctionne pas parce que vous n'avez pas à spécifier le nœud racine. Maintenant, une approche similaire peut être trouvé ici. Dans celui-ci, ils spécifier l'attribut xmlrootattribute lors de la déclaration du sérialiseur. la vôtre devrait ressembler à ceci:solution combinée bits. Yay. Content d'avoir pu aider à bien =D
OriginalL'auteur Nevyn
Ici vous allez...
OriginalL'auteur Mike