开发者

Parse XML using LINQ and fill existing object's properties rather than creating a new one

What I have now is the following code:

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 is passed from another method. And the code below has to 'fill' it.

The question is: Is there a way to create a LINQ query, which will assign values to the properties of an existing object, rather that creating a new one.

I would like my code to look something like this:

   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),
   });

The problem I have is: I have an object which initially only has half of it's properties set, later I need to fill the rest of the properties. This needs to be done asynchronously.

My Approach: I use WebClient's asynchronous method DownloadStringAsync to download XML file. In the event handler I wan't to fill an object with the propert开发者_Python百科ies it misses. And that's why I would like to directly pass values to my object rather than creating a new one.

Please let me know if it is not the best approach.


OK, this is pure evil:

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();


LINQ functional queries are actually designed in such way, that they shouldn't modify existing objects or collections, i.e. preserve state (although there are ways (hacks?) to do so).

But you can pretty easily implement reflection-based method to achieve what you want.


I noticed this question and felt the need to add another dirty solution. How about Extension methods?

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;
}

Now you can just call it to add to your current tutorial. Also, I recommend using (string) instead of .Value so you avoid null reference exceptions.

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);

Anyway, Good luck. Just wanted to add a dirty solution to this ball of mud.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜