2017-05-07 2 views
1

Le code ci-dessous fonctionne actuellement et charge le code XML dans une structure de classe. Cette structure consiste en une collection d'éléments (éléments), chacun ayant des propriétés statiques et une collection que j'utilise pour un nombre variable de propriétés. Deux choses que je veux faire: 1) Je veux changer la liste en quelque chose qui a une clé unique. J'ai essayé un dictionnaire et cela n'a pas fonctionné, peut-être un HashSet ... conduisant à ... 2) La clé de la collection devrait être pilotée par l'attribut XML "id" de l'élément.C# Désérialise le code XML dans une collection à clé unique où la clé provient de l'attribut XML "Id"

Je n'arrive pas à le comprendre, et essayer de copier le modèle KVP que j'ai utilisé pour les paramètres d'une variable d'élément ne fonctionne pas. Il ajoute les éléments aux "éléments" mais ils sont tous vides et le hachage de la collection n'est pas renseigné.

Aide s'il vous plaît

[XmlRoot("ItemsContainer")] 
public class Items 
{ 
    [XmlAttribute("Version")] 
    public string Version { get; set; } 

    [XmlArray("Items")] 
    [XmlArrayItem("Item")] 
    public List<Item> items = new List<Item>(); //TODO - The key in this collection should be unique and driven from an item's "Id" XML attribute 

    public static Items Load(string path) 
    { 
     var xml = Resources.Load<TextAsset>(path); 
     var serializer = new XmlSerializer(typeof (Items)); 
     var reader = new StringReader(xml.text); 
     var items = (Items) serializer.Deserialize(reader); 
     reader.Close(); 
     return items; 
    } 
} 


public class Item 
{ 
    //### Fixed Item Parameters 
    [XmlAttribute("Id")] 
    public int Id { get; set; } 

    [XmlElement("Name")] 
    public string Name { get; set; } 

    [XmlElement("Description")] 
    public string Description { get; set; } 

    [XmlElement("Value")] 
    public float Value { get; set; } 

    //### Variable Item Parameters as Key Value pairs. 
    [XmlArray("KVPS")] 
    [XmlArrayItem("KVP")] 
    public List<KeyValuePair<string, string>> KVPS { get; set; } //We will have cases were we don't want unique keys 
} 

[Serializable] 
public class KVP<K, V> 
{ 
    public K Key { get; set; } 
    public V Value { get; set; } 

    public KVP() 
    { 
    } 

    public KVP(K key, V value) 
    { 
     Key = key; 
     Value = value; 
    } 
} 

Voici le XML

<?xml version="1.0" encoding="utf-8"?> 

<ItemsContainer Version="1.0"> 
    <Items> 

    <Item Id="100"> 
     <Name>Burger</Name> 
     <Description>The lovely tasting Big Mac</Description> 
     <Value>5.67</Value> 
    </Item> 

    <Item Id="101"> 
     <Name>Sammich</Name> 
     <Description>Ham and cheese</Description> 
     <Value>2.80</Value> 
    </Item> 

    <Item Id="102"> 
     <Name>Carling</Name> 
     <Description>Pint of carling</Description> 
     <Value>2.80</Value> 
     <KVPS> 
     <KVP> 
      <Key>alchohol</Key> 
      <Value>3.9</Value> 
     </KVP> 
     <KVP> 
      <Key>alchohol</Key> 
      <Value>4.9</Value> 
     </KVP> 
     <KVP> 
      <Key>alchohol</Key> 
      <Value>5.9</Value> 
     </KVP> 
     </KVPS> 
    </Item> 

    </Items> 
</ItemsContainer> 
+0

Vous souhaitez donc que Id génère la clé unique créée? Que faire si ID est dupliqué, comment la clé doit-elle être créée uniquement? Inversement, si Id n'est pas dupliqué, il est unique, alors pourquoi ne pas utiliser Id? – Snympi

+0

> Vous voulez donc que Id conduise la clé unique créée? Oui, cela a été mentionné dans mon OP. > Que faire si l'ID est dupliquée. Comme je l'ai mentionné c'est pour entrer dans un dictionnaire, donc la même manipulation. > comment la clé devrait-elle être créée uniquement? La clé a déjà été créée dans le fichier XML donc ce n'est pas un problème ici. Inversement, si Id n'est pas dupliqué, il est unique, alors pourquoi ne pas utiliser Id? C'est ce que je demande dans mon OP –

Répondre

1

associée Essayez quelque chose comme ça. J'ai changé StringReader en StreamReader juste pour mes tests. Vous pouvez le modifier

public static Dictionary<int, Item> Load(string path) 
     { 
      //var xml = Resources.Load<TextAsset>(path); 
      XmlSerializer serializer = new XmlSerializer(typeof(Items)); 
      StreamReader reader = new StreamReader(path); 
      Items items = (Items)serializer.Deserialize(reader); 
      reader.Close(); 
      Dictionary<int, Item> dict = items.items.GroupBy(x => x.Id).ToDictionary(x => x.Key, y => y.FirstOrDefault()); 
      return dict; 
     } 
+0

Ce fut le type de méthode que je suis allé avec à la fin qui, à proprement parler, je vois comme une alternative plutôt qu'une solution. La raison pour laquelle je dis cela est parce qu'une étape supplémentaire est ajoutée pour copier la liste dans un dictionnaire plutôt que d'utiliser le dictionnaire directement depuis le début. Une façon de le faire en une étape est de parcourir manuellement le XML en utilisant XDocument ou d'utiliser IXmlSerializable et de faire quelque chose de similaire. Cependant, je pense que pour cette portée, cela devrait être considéré comme la solution. –

+0

Vous pouvez utiliser items.items.GroupBy (x => x.Id) .ToList() pour obtenir chaque élément. Puis énumérer à travers la liste en ajoutant chacun au dictionnaire existant. Ajouter (x.Key, x) – jdweng