重构查询以选择类型的lst

时间:2019-01-06 11:37:37

标签: c# linq select

尽管此方法可以正常工作。我相当确定可以在查询中完成所有这些操作(即返回CreatorsDto类型的列表)。我已经搜索了很多方法,但是一无所获。

此方法从xml文件中提取数据,该文件的格式为;

<?xml version="1.0" encoding="utf-8" ?>
<Creators>
  <Creator name="name here" field="field here">
    <ImageUrl value="url here" />
    <SocialLinks>
      <Twitter value="www.twitter.com/twitter handle here" />
      <Facebook value="www.facebook.com/facebook handle here" />
      <Linkedin value="www.linkedin.com/linkedin handle here" />
      <Instagram value="www.instagram.com/insta handle here" />
    </SocialLinks>
  </Creator>

和方法

public List<CreatorsDto> BuildModelFromCreatorsXmlFile()
{
    var cvmList = new List<CreatorsDto>();
    var result = _doc.Descendants("Creator")
        .Where(a => (string) a.Attribute("name") != string.Empty)
        .Where(a => (string) a.Attribute("field") != string.Empty)
        .ToList();
    foreach (var creator in result)
    {
        var cvm = new CreatorsDto
        {
            CreatorField = creator.Attribute("field")?.Value,
            CreatorName = creator.Attribute("name")?.Value,
            CreatorHeadShotUrl = creator.Element("ImageUrl")?.Attribute("value")?.Value
        };
        var dict = new Dictionary<string,string>();
        foreach (var link in creator.Element("SocialLinks") != null
                ? creator.Element("SocialLinks").Descendants()
                : null)
        {
            dict.Add(link.Name.ToString(),link.Attribute("value")?.Value);
        }
            cvm.SocialLinks = dict;
            cvmList.Add(cvm);
        }

     return cvmList;
}

我知道在最后一个Where子句之后,我需要一个Select语句

.Where(a => (string) a.Attribute("field") != string.Empty)
.Select( new CreatorsDto
    {
       // everything I try in here is no good
    })
 .ToList();

任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

如果您希望在“一个”查询中使用完整的逻辑,则其外观可能类似于以下代码:

document.Descendants("Creator")
        .Where(creator => string.IsNullOrEmpty((string)creator.Attribute("name")) == false)
        .Where(creator => string.IsNullOrEmpty((string)creator.Attribute("field")) == false)
        .Select(creator =>
        {
            return new CreatorDto
            {
                Name = creator.Attribute("name").Value,
                Field = creator.Attribute("field").Value,
                ImageUrl = creator.Element("ImageUrl")?.Attribute("value")?.Value,
                SocialLinks = 
                    (creator.Element("SocialLinks") ?? new XElement("SocialLinks"))
                        .Elements()
                        .ToDictionary(link => link.Name.ToString(), 
                                      link => (string)link.Attribute("value"))
            };
        })
        .ToList();

Where内部使用Select查询后使用空传播是多余的。
对于集合类型,最好的做法是从不返回null-在没有数据时返回空集合(在这种情况下为Dictionary)。

答案 1 :(得分:0)

您需要像对Select表达式那样将参数传递给Where lambda表达式。一种可能的解决方案是

public List<CreatorsDto> BuildModelFromCreatorsXmlFile()
{
    return _doc.Descendants("Creator")
        .Where(a => (string) a.Attribute("name") != string.Empty)
        .Where(a => (string) a.Attribute("field") != string.Empty)
        .Select(a => new CreatorsDto
            {
                CreatorField = a.Attribute("field")?.Value,
                CreatorName = a.Attribute("name")?.Value,
                CreatorHeadShotUrl = a.Element("ImageUrl")?.Attribute("value")?.Value,
                SocialLinks = a.Element("SocialLinks")?.Descendants().ToDictionary(link => link.Name.ToString(), link => link.Attribute("value")?.Value)
            })  
        .ToList();
}