tags:

views:

200

answers:

2

I am looking for a nice way to save / load the following. I want to save as XML and ideally looking to use LiNQ (namely to help me learn LINQ)

I don't know how to do nested linq writes though. Can anyone help?

    /// <summary>
/// 
/// </summary>
public class ErrorType
{
    List<ErrorType> _childErrors;

    public String Name { get; set; }
    public bool Ignore { get; set; }

    public List<ErrorType> ChildErrors { get; protected set; }
}

/// <summary>
/// 
/// </summary>
public class ErrorList
{
    public List<ErrorType> ChildErrors { get; protected set; }

    public void Save()
    {
    }

    public void Load()
    {
    }
}

Essentially the ErrorList contains a top level list of Errors, each error can have children. The XML output should look something like:

<ErrorList>
<ErrorName1 Ignore="false">
<ChildErrorName1 Ignore="true">
<ChildErrorName2 Ignore="false" />
</ChildErrorName1>
</ErrorName1>
<ErrorList>

If anyone could help that would be great. Thanks

A: 

Have a look at this. It should be what you are looking for. No LINQ thought but rather nice and easy way of outputting XML.

The bottom line though is to use XmlSerializer.

Sani Huttunen
+1  A: 

Okay, I think I see what you're after now. Try this:

// Need to declare in advance to call within the lambda.
Func<ErrorType, XElement> recursiveGenerator = null;
recursiveGenerator = error => new XElement
    (error.Name,
     new XAttribute("Ignore", error.Ignore),
     error.ChildErrors.Select(recursiveGenerator));

var errorList = new XElement
    ("ErrorList", errors.ChildErrors.Select(recursiveGenerator));

Here's a complete example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

public class ErrorType
{
    public String Name { get; set; }
    public bool Ignore { get; set; }

    public List<ErrorType> ChildErrors { get; protected set; }
    public ErrorType()
    {
        ChildErrors = new List<ErrorType>();
    }
}

public class ErrorList
{
    public List<ErrorType> ChildErrors { get; protected set; }
    public ErrorList()
    {
        ChildErrors = new List<ErrorType>();
    }
}

public class Test
{
    public static void Main()
    {
        var childError2 = new ErrorType { 
            Name = "ChildErrorName2", Ignore=false };
        var childError1 = new ErrorType {
            Name = "ChildErrorName1", Ignore=true,
            ChildErrors = { childError2 }
        };
        var mainError = new ErrorType {
            Name = "ErrorName1", Ignore=true,
            ChildErrors = { childError1 }
        };
        var errorList = new ErrorList { ChildErrors = { mainError } };

        // Need to declare in advance to call within the lambda.
        Func<ErrorType, XElement> recursiveGenerator = null;
        recursiveGenerator = error => new XElement
            (error.Name,
             new XAttribute("Ignore", error.Ignore),
             error.ChildErrors.Select(recursiveGenerator));

        var element = new XElement
             ("ErrorList", 
              errorList.ChildErrors.Select(recursiveGenerator);

        Console.WriteLine(element);
    }        
}
Jon Skeet
Cheers Jon that looks about right.I tested it though and it has a compiler error on the line: errorList.ChildErrors.Select(recursiveGenerator(x));I replaced X with errorList.ChildErrors[0] to match the correct type but no joy. My lambda skills are weak so couldn't figure out what was going wrong.
Chris
Whoops, fixed that - it should be errorList.ChildErrors.Select(recursiveGenerator);
Jon Skeet
(I used to have errorList.ChildErrors.Select(x => recursiveGenerator(x)) which is a bit redundant.)
Jon Skeet
Thanks that looks good, how would I reverse this to actually load data from an XElement?
Chris
So far I have this... private ErrorList FromXmlToErrorList(XElement xd) { List<ErrorType> typeList = (from error in xd.Descendants() select new ErrorType { Name = error.Value, Ignore = bool.Parse(error.Attribute("Ignore").Value) ChildErrors= /*Lambda ?*/ }).ToList<ErrorType>(); ErrorList el = new ErrorList(); el.ChildErrors = typeList; return el; }
Chris
Um, I suggest you ask in a separate question - it'll be slightly messy to mix up that with the answer here (which is already quite long). I'll happily answer though :)
Jon Skeet
Cheers dude I'll get on it :)
Chris