2010-08-06 28 views
1

Je suis en train de tirer le Roles ci-dessous dans un IEnumerable<KeyValuePair<int, string>>Linq: Xml à IEnumerable <KeyValuePair <int, string>> exécution différée?

<PROJECT PROJECT_NO="161917"> 
    <CONTACT CLIENT_ID="030423253272735482765C" CONTACT_NO="1"> 
    <ROLE ROLE_ID="2" ROLE_DESC="ARCHITECT" /> 
    <ROLE ROLE_ID="5" ROLE_DESC="INTEGRATOR" /> 
    </CONTACT> 
</PROJECT> 



private static ProjectContact BuildProjectContactFromXml(XElement xml) 
    { 
     ProjectContact projectContact = new ProjectContact(); 
     projectContact.ProjectId = SafeConvert.ToInt32(xml.Attribute("PROJECT_NO").Value); 
     projectContact.Roles = xml.Elements() 
            .First() 
            .Elements() 
            .Select(role => new KeyValuePair<int, string>(
                  SafeConvert.ToInt32(role.Attribute("ROLE_ID").Value), 
                  role.Attribute("ROLE_DESC").Value)); 

     return projectContact; 
    } 

Ma question porte sur l'exécution différée de cette déclaration LINQ. Je crois comprendre que lorsque je renvoie ce ProjectContact, l'instruction Linq n'est pas encore exécutée. Existe-t-il un moyen de forcer l'exécution de cette instruction pour qu'elle se produise dans cette méthode plutôt que lorsque quelqu'un tente d'accéder aux rôles? Je pense que je pourrais forcer l'exécution de la déclaration en appelant .Count() dessus, mais il semble qu'il devrait y avoir un meilleur moyen.

+0

Désolé, n'était pas fini avec la question et il a posté! Je vais finir d'écrire ma question, une minute :) – JSprang

+0

Ok, la question est là maintenant. – JSprang

+0

Roles est un IEnumerable >, désolé à ce sujet. – JSprang

Répondre

2

projectContact.Roles va être un IEnumerable<KeyValuePair<int, string>> est ce que vous voulez, ou voulez-vous comme une liste ou un commentaire? Pour une liste, il suffit de taper .ToList() à la fin de l'instruction.

Pour un dictionnaire, il est un peu plus compliqué:

projectContact.Roles = xml.Elements() 
           .First() 
           .Elements() 
           .ToDictionary(
       role=> SafeConvert.ToInt32(role.Attribute("ROLE_ID").Value), 
       role=> role.Attribute("ROLE_DESC").Value)); 

MISE À JOUR: En vous vous déclarez que les rôles commentaires que id IEnumerable<KeyValuePair<int, string>>. Techniquement, cela pourrait être soit un dictionnaire ou une liste, bien que dans le premier cas, vous ne pouvez vraiment pas utiliser son dictionnaire par l'intermédiaire de cette interface. D'ailleurs, vous pouvez utiliser beaucoup de List-ness dans le dernier cas - mais il semble que vous ne vouliez pas cette capacité.

Donc, virer sur .ToList();. Ce sera une liste dans les coulisses, mais sans aller à des longueurs extradinaires, les utilisateurs seront toujours seulement en mesure de l'utiliser comme un IEnumerable.

+0

Sur le ProjectContact, je veux que les rôles soient un IEnumerable. La raison en est que je ne veux pas que l'utilisateur de l'objet puisse éditer la collection de rôles. Si je l'ai fait une liste ou un dictionnaire, ils pourraient lui ajouter(). Cela a-t-il du sens? – JSprang

+0

Ah, oui! Ça a du sens! Merci d'avoir expliqué! – JSprang

+0

@JSPrang: Notez cependant que "longueurs extradinaires" est à peu près juste de lancer ... –

2

Si le type de données de .Roles est un tableau, vous pouvez simplement ajouter .ToArray() après votre .Select(), ce qui garantit que la requête est exécutée. De toute façon, vous pouvez exécuter un ToList() ou .ToArray(), et vous obtiendrez l'exécution de la requête.