2010-12-09 38 views
2

Ce que j'est maintenant le code suivant:Parse XML en utilisant LINQ et remplir les propriétés d'un objet existant plutôt que de créer un nouveau

Tutorial tutorial = 
    (from tutorial in xmlDoc.Descendants("Tutorial") 
    select new Tutorial 
    { 
    Author = tutorial.Element("Author").Value, 
    Title = tutorial.Element("Title").Value, 
    Date = DateTime.Parse(tutorial.Element("Date").Value), 
    }).First(); 

myTutorial.Author = tutorial.Author; 
myTutorial.Title = tutorial.Title; 
myTutorial.Date = tutorial.Date; 

myTutorial est passé d'une autre méthode. Et le code ci-dessous doit le "remplir".

La question est: existe-t-il un moyen de créer une requête LINQ, qui affectera des valeurs aux propriétés d'un objet existant, plutôt que de créer un nouveau.

Je voudrais que mon code pour ressembler à ceci:

Tutorial tutorial = 
    (from tutorial in xmlDoc.Descendants("Tutorial") 
    select myTutorial 
    { 
    Author = tutorial.Element("Author").Value, 
    Title = tutorial.Element("Title").Value, 
    Date = DateTime.Parse(tutorial.Element("Date").Value), 
    }); 

Le problème que j'ai est: J'ai un objet qui a d'abord seulement la moitié de ses propriétés de définir, plus tard, je dois remplir le reste des propriétés. Cela doit être fait de manière asynchrone.

Mon approche: J'utilise la méthode asynchrone de WebClientDownloadStringAsync pour télécharger le fichier XML. Dans le gestionnaire d'événements, je ne veux pas remplir un objet avec les propriétés qui lui manquent. Et c'est pourquoi je voudrais passer directement des valeurs à mon objet plutôt que d'en créer une nouvelle.

S'il vous plaît laissez-moi savoir si ce n'est pas la meilleure approche.

+2

Etes-vous sûr que le 1er exemple est compilé? Je pense que vous avez besoin d'un .First() là-bas. –

+0

oui oui! Je viens de taper le code ici, donc j'ai manqué le .First(). – Vitalij

+1

btw, vous pourriez vouloir noter l'utilisation de * cast * plutôt que '.Value' dans la réponse que je donne; en plus d'utiliser les formats xml corrects (ie les dates xml ne sont pas les mêmes que 'DateTime.Parse') cela réagit de manière appropriée si des éléments sont manquants - par exemple lancer à' (DateTime?) 'retournera une valeur nulle si l'élément est manquant, plutôt que le '.Value' étant une exception null-ref. –

Répondre

1

OK, c'est mal pur:

var dropThis = 
    (from tutorial in xmlDoc.Descendants("Tutorial") 
    select new 
    { 
    Author = (myTutorial.Author = (string)tutorial.Element("Author")), 
    Title = (myTutorial.Title = (string)tutorial.Element("Title")), 
    Date = (myTutorial.Date = (DateTime)tutorial.Element("Date")), 
    }).First(); 
+0

Oui, cela devrait fonctionner. Mais a l'air assez mal :) Donc autant que je peux comprendre, vous devez créer un objet si vous analysez XML en utilisant LINQ. – Vitalij

+0

Eh bien, en quelque sorte; vous devez satisfaire une projection. Il y a d'autres choses que vous pourriez faire au lieu de 'new' - mais assigner 3 accessoires est l'astuce. –

0

Les requêtes fonctionnelles LINQ sont conçues de telle sorte qu'elles ne doivent pas modifier les objets ou collections existants, c'est-à-dire préserver l'état (bien qu'il existe des moyens (hacks?) De le faire).

Mais vous pouvez facilement mettre en œuvre une méthode basée sur la réflexion pour obtenir ce que vous voulez.

0

Je remarqué cette question et ont ressenti le besoin d'ajouter une autre solution sale. Qu'en est-il des méthodes d'extension?

public static void AddTo(this IEnumerable<Tutorial> source, Tutorial projection) 
{ 
    if (source.Count() == 0) 
     return; 

    projection.Title = source.First().Title; 
    projection.Author = source.First().Author; 
    projection.Date = source.First().Date; 
} 

Vous pouvez maintenant l'appeler pour l'ajouter à votre didacticiel actuel. En outre, je recommande d'utiliser (chaîne) au lieu de .Value pour éviter les exceptions de référence nulles.

tutorialXml 
    .Descendants("Tutorial") 
    .Select(tutorial => new Tutorial 
     { 
      Author = (string) tutorial.Element("Author"), 
      Title = (string) tutorial.Element("Title"), 
      Date = DateTime.Parse((string) tutorial.Element("Date")), 
     }) 
    .AddTo(myTutorial); 

De toute façon, bonne chance. Je voulais juste ajouter une solution sale à cette boule de boue.