Вложенный Linq для создания нескольких объектов класса - PullRequest
1 голос
/ 06 октября 2009

Я ищу создание динамического меню навигации XML, которое состоит из MenuItem и SubMenuItem (оба класса). Я хочу проанализировать следующий XML и использовать LINQ для его анализа и получения данных.

Вот пример XML:

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

<MenuItems>
  <Item Id="1" Url="Default.aspx" LinkText="Home" Description="Test Description" Target="">
    <SubItem Id="1" ParentId="1" Url="Default.aspx" LinkText="SubMenu1" Description="Test Description" Target="" />
    <SubItem Id="2" ParentId="1" Url="Default.aspx" LinkText="SubMenu2" Description="Test Description" Target="" />
    <SubItem Id="3" ParentId="1" Url="Default.aspx" LinkText="SubMenu3" Description="Test Description" Target="" />
  </Item>
  <Item Id="2" Url="Default2.aspx" LinkText="Menu2" Description="Test Description" Target="" />
  <Item Id="3" Url="Default3.aspx" LinkText="Menu3" Description="Test Description" Target="" />
</MenuItems>

Я хочу использовать LINQ, но у меня проблемы с синтаксисом. Можете ли вы использовать вложенные запросы LINQ для заполнения двух списков объектов, как показано ниже?

List<MenuItem> MenuItems = null;
try
{
    XElement xmlDoc = XElement.Load(xmlPath + xmlFileName);
    if (xmlDoc != null)
    {
        MenuItems =
                (from menuItem in xmlDoc.Descendants("Item")
                select new MenuItem
                {
                    Id = menuItem.Attribute("Id").Value,
                    Description = menuItem.Attribute("Description").Value,
                    LinkText = menuItem.Attribute("LinkText").Value,
                    Url = menuItem.Attribute("Url").Value,
                    Target = menuItem.Attribute("Description").Value,
                    SubMenuItems = (from subMenuItem in xmlDoc.Descendants("SubItem")
                                    select new SubMenuItem
                                    {
                                        Id = menuItem.Attribute("Id").Value,
                                        ParentId = menuItem.Attribute("ParentId").Value,
                                        Description = menuItem.Attribute("Description").Value,
                                        LinkText = menuItem.Attribute("LinkText").Value,
                                        Url = menuItem.Attribute("Url").Value,
                                        Target = menuItem.Attribute("Description").Value,
                                    }).ToList<SubMenuItem>(),
                }).ToList<MenuItem>();
    }
}

Может ли кто-нибудь помочь с LINQ разбить этот XML на эти два класса, которые вложены друг в друга?

public class MenuItem
{
    public MenuItem() { }

    private string id;
    private string url;
    private string linkText;
    private string description;
    private string target;
    private List<SubMenuItem> subMenuItems = new List<SubMenuItem>();

    public string Id { get { return id; } set { id = value; } }
    public string Url { get { return url; } set { url = value; } }
    public string LinkText { get { return linkText; } set { linkText = value; } }
    public string Description { get { return description; } set { description = value; } }
    public string Target { get { return target; } set { target = value; } }
    public List<SubMenuItem> SubMenuItems { get { return subMenuItems; } set { subMenuItems = value; } }
}

public class SubMenuItem
{
    public SubMenuItem() { }

    private string id;
    private string parentid;
    private string url;
    private string linkText;
    private string description;
    private string target;

    public string Id { get { return id; } set { id = value; } }
    public string ParentId { get { return parentid; } set { parentid = value; } }
    public string Url { get { return url; } set { url = value; } }
    public string LinkText { get { return linkText; } set { linkText = value; } }
    public string Description { get { return description; } set { description = value; } }
    public string Target { get { return target; } set { target = value; } }
}

Спасибо!

Ответы [ 2 ]

2 голосов
/ 06 октября 2009

Может помочь, если вы немного больше изолируете свою логику.Лучше всего, IMO, было бы добавить конструктор к MenuItem и SubMenuItem, который принимает XElement.

public class MenuItem
{
    public MenuItem() { }

    public MenuItem(XElement xmlDoc)
    {
        this.id = xmlDoc.Element("Id").Value;
        this.url = xmlDoc.Element("Url").Value;
        // etc.
        subMenuItems = (from subMenuItem in xmlDoc.Descendants("SubItem")
                        select new SubMenuItem(subMenuItem)).ToList();

    // etc.
}

public class SubMenuItem
{
    public SubMenuItem() { }

    public SubMenuItem(XElement xmlDoc)
    {
        this.id = xmlDoc.Element("Id").Value;
        // etc.
    }
    // etc.
}

Это очистило бы ваш первоначальный выбор:

MenuItems = (from menuItem in xmlDoc.Descendants("Item")
             select new MenuItem(menuItem)).ToList();
1 голос
/ 06 октября 2009

Я думаю, вы могли бы решить эту проблему с помощью небольшой рекурсии.Вы могли бы, вероятно, иметь только MenuItem вместо обоих классов.Они в основном одинаковы.Затем, если вы создадите метод SelectDecendants, он будет продолжать вызывать себя, чтобы получить дочерние элементы текущего узла.Как то так:

class Program
{
    static void Main(string[] args)
    {
        var doc = XDocument.Load("input.xml");
        var menuItems = SelectDescendants(doc.Elements("MenuItems").Elements());
    }

    public static List<MenuItem> SelectDescendants(IEnumerable<XElement> menuItems)
    {
        return (from menuItem in menuItems
                    select new MenuItem
                    {
                        Id = menuItem.Attribute("Id").Value,
                        Description = menuItem.Attribute("Description").Value,
                        LinkText = menuItem.Attribute("LinkText").Value,
                        Url = menuItem.Attribute("Url").Value,
                        Target = menuItem.Attribute("Description").Value,
                        SubMenuItems = SelectDescendants(menuItem.Elements()).ToList()
                    }).ToList();
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...