【问题标题】:Linq: Xml to IEnumerable<KeyValuePair<int, string>> deferred execution?Linq:Xml 到 IEnumerable<KeyValuePair<int, string>> 延迟执行?
【发布时间】:2011-03-26 10:10:03
【问题描述】:

我正在尝试将下面的Roles 提取到IEnumerable&lt;KeyValuePair&lt;int, string&gt;&gt;

<PROJECT PROJECT_NO="161917"> 
  <CONTACT CLIENT_ID="030423253272735482765C" CONTACT_NO="1"> 
    <ROLE ROLE_ID="2" ROLE_DESC="ARCHITECT" /> 
    <ROLE ROLE_ID="5" ROLE_DESC="INTEGRATOR" /> 
  </CONTACT>
</PROJECT>



private static ProjectContact BuildProjectContactFromXml(XElement xml)
    {
        ProjectContact projectContact = new ProjectContact();
        projectContact.ProjectId = SafeConvert.ToInt32(xml.Attribute("PROJECT_NO").Value);
        projectContact.Roles = xml.Elements()
                                    .First()
                                    .Elements()
                                    .Select(role => new KeyValuePair<int, string>(
                                                            SafeConvert.ToInt32(role.Attribute("ROLE_ID").Value), 
                                                            role.Attribute("ROLE_DESC").Value));

        return projectContact;
    }

我的问题是关于延迟执行此 Linq 语句。据我了解,当我返回这个 ProjectContact 时,Linq 语句尚未执行。有没有办法强制执行这个语句,以便它发生在这个方法中,而不是当有人试图访问角色时?我想我可以通过调用 .Count() 来强制执行该语句,但似乎应该有更好的方法。

【问题讨论】:

  • 抱歉,问题未完成,已发布!我会写完我的问题,一分钟 :)
  • Roles 是一个 IEnumerable>,抱歉。
  • 在 .NET 4 中,它们现在具有元组,因此我们不必再为这些东西创建键值对列表。新元组(int value1, string value2)
  • @Jimmy Hoffa,很酷,不知道,但我目前正在从事 3.5 项目。谢谢!
  • @Jimmy Hoffa:我相信语法实际上是Tuple.Create(int value1, string value2)(从参数推断的类型没有指定)

标签: c# xml linq .net-3.5 deferred-execution


【解决方案1】:

projectContact.Roles 将成为IEnumerable&lt;KeyValuePair&lt;int, string&gt;&gt; 是你想要的,还是你想要它作为一个列表或字典?对于列表,只需在语句末尾添加.ToList()

对于字典,它有点棘手:

   projectContact.Roles = xml.Elements() 
                                .First() 
                                .Elements()
                                .ToDictionary(
                 role=> SafeConvert.ToInt32(role.Attribute("ROLE_ID").Value),
                 role=> role.Attribute("ROLE_DESC").Value)); 

更新:在您的 cmets 中,您声明角色 ID IEnumerable&lt;KeyValuePair&lt;int, string&gt;&gt;。从技术上讲,它可以是字典或列表,尽管在前一种情况下,您确实不能通过该接口使用它的字典特性。就此而言,您可以在后一种情况下使用它的大部分 List-ness - 但似乎您特别不想要这种能力。

所以,继续.ToList();。它将是一个幕后的列表,但无需特别冗长,用户仍然只能将其用作 IEnumerable。

【讨论】:

  • 在 ProjectContact 上,我确实希望角色是 IEnumerable。原因是我不希望对象的用户能够编辑角色集合。如果我将其设为列表或字典,他们将能够向其添加()。这有意义吗?
  • 啊,是的!这就说得通了!感谢您的解释!
【解决方案2】:

如果.Roles 的数据类型是数组,您可以在.Select() 之后简单地附加.ToArray(),这样可以确保执行查询。

无论哪种方式,您都可以执行ToList().ToArray(),然后您将执行查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多