【问题标题】:How to Join two IEnumerables with anonymous types?如何使用匿名类型加入两个 IEnumerables?
【发布时间】:2016-08-31 14:19:44
【问题描述】:

我正在使用 Linq-to-Xml 创建两个 IEnumerables 但我想将第二个列表的结果与第一个列表结合起来。当我使用.Concat() 时,出现以下错误:

'IQueryable' 不包含'Concat' 的定义,并且最佳扩展方法重载'ParallelEnumerable.Concat(ParallelQuery, IEnumerable)' 需要'ParallelQuery' 类型的接收器

我正在尝试.Concat() 的两个列表在这里:

var findingDetails = from f in element.Elements(ns + "Group")
                     select new
                     {
                         testID = (string)f.Attribute("id").Value,
                         title = (string)f.Element(ns + "title"),
                         idrefFD = (string)f.Element(ns + "Rule").Attribute("id").Value,
                         severity = (string)f.Element(ns + "Rule").Attribute("severity").Value,
                         description = (string)f.Element(ns + "Rule").Element(ns + "description"),
                         fixText = (string)f.Element(ns + "Rule").Element(ns + "fixtext")
                     };
var getStatus = from gs in element.Descendants(ns + "rule-result")
                select new
                {
                    idrefStatus = (string)gs.Attribute("idref").Value,
                    result = (string)gs.Element(ns + "result"),
                    dateTime = (string)gs.Attribute("time")
                };

错误是在findingDetails这里使用产生的:

var combined = findingDetails.Concat(getStatus);

我想要得到的是一个var,它包含findingDetails + getStatus.resultgetStatus.dateTime 的所有内容,在一个地方。这就是为什么我只需要遍历一个foreach() 循环来访问所有值,而不是使用嵌套的foreach() 循环。

示例 XML 文档:

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

<cdf:Benchmark style="SCAP_1.1" resolved="1" id="RHEL_6_STIG" xsi:schemaLocation="http://checklists.nist.gov/xccdf/1.1 http://nvd.nist.gov/schema/xccdf-1.1.4.xsd http://cpe.mitre.org/dictionary/2.0 http://scap.nist.gov/schema/cpe/2.2/cpe-dictionary_2.2.xsd" xmlns:cdf="http://checklists.nist.gov/xccdf/1.1" xmlns:cpe="http://cpe.mitre.org/dictionary/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <cdf:status date="2016-04-22">accepted</cdf:status>
  <cdf:title>Red Hat Enterprise Linux 6 Security Technical Implementation Guide</cdf:title>
  <cdf:description>The Red Hat Enterprise Linux 6 Security Technical Implementation Guide (STIG) is published as a tool to improve the security of Department of Defense (DoD) information systems.  Comments or proposed revisions to this document should be sent via e-mail to the following address: disa.stig_spt@mail.mil.</cdf:description>
  <cdf:notice id="terms-of-use"></cdf:notice>
  <cdf:reference href="http://iase.disa.mil">
        <dc:publisher>DISA</dc:publisher>
        <dc:source>STIG.DOD.MIL</dc:source>
  </cdf:reference>
  <cdf:plain-text id="release-info">Release: 11 Benchmark Date: 22 Apr 2016</cdf:plain-text>
  <cdf:platform idref="cpe:/o:redhat:enterprise_linux:6"></cdf:platform>
  <cdf:version>1</cdf:version>
  <cdf:Profile id="MAC-1_Classified">
        <cdf:title>I - Mission Critical Classified</cdf:title>            
  </cdf:Profile>
  <cdf:Value id="var_umask_for_daemons">
        <cdf:title>daemon umask</cdf:title>
        <cdf:description>Enter umask for daemons</cdf:description>
        <cdf:value>022</cdf:value>
        <cdf:value selector="022">022</cdf:value>
        <cdf:value selector="027">027</cdf:value>
  </cdf:Value>
  <cdf:Group id="V-7055">
        <cdf:title>APPNET0031 No Strong Name Verification</cdf:title>
              <cdf:description>&lt;GroupDescription&gt;&lt;/GroupDescription&gt;</cdf:description>
            <cdf:Rule weight="10.0" id="SV-7438r2_rule" severity="medium">
                  <cdf:version>APPNET0031</cdf:version>
                  <cdf:title>Digital signatures assigned to strongly named assemblies must be verified.</cdf:title>
                  <cdf:description>&lt;VulnDiscussion&gt;A strong name consists of the assembly's identity, simple text name, version number, and culture information (if provided)—plus a public key and a digital signature.  Strong names serve to identify the author of the code.  If digital signatures used to sign strong name assemblies are not verified, any self signed code can be impersonated.  This can lead to a loss of system integrity. &lt;/VulnDiscussion&gt;&lt;FalsePositives&gt;&lt;/FalsePositives&gt;&lt;FalseNegatives&gt;&lt;/FalseNegatives&gt;&lt;Documentable&gt;false&lt;/Documentable&gt;&lt;Mitigations&gt;&lt;/Mitigations&gt;&lt;SeverityOverrideGuidance&gt;&lt;/SeverityOverrideGuidance&gt;&lt;PotentialImpacts&gt;&lt;/PotentialImpacts&gt;&lt;ThirdPartyTools&gt;&lt;/ThirdPartyTools&gt;&lt;MitigationControl&gt;&lt;/MitigationControl&gt;&lt;Responsibility&gt;System Administrator&lt;/Responsibility&gt;&lt;IAControls&gt;DCSL-1&lt;/IAControls&gt;</cdf:description>
                  <cdf:reference>
                        <dc:publisher>DISA</dc:publisher>
                        <dc:identifier>2030</dc:identifier>
                        <dc:type>DPMS Target</dc:type>
                  </cdf:reference>
                  <cdf:fixtext fixref="F-12596r7_fix">Use regedit to remove the values stored in Windows registry key hKLM\Software\Microsoft\StrongName\Verification. There should be no assemblies or hash values listed under this registry key. All assemblies must require strong name verification in a production environment. Strong name assemblies that do not require verification in a development or test environment must have documented approvals from the IAO.</cdf:fixtext>
                  <cdf:fix id="F-12596r7_fix"></cdf:fix>
                  <cdf:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
                        <cdf:check-content-ref href="U_Microsoft_DotNet_Framework_4_V1R4_STIG_SCAP_1-1_Benchmark-oval.xml" name="oval:mil.disa.fso.dotnet:def:2"></cdf:check-content-ref>
                  </cdf:check>
            </cdf:Rule>
      </cdf:Group>
      <cdf:TestResult start-time="2016-07-20T11:59:59" version="1" test-system="cpe:/a:spawar:scc:4.1" end-time="2016-07-20T12:00:50" id="U_Microsoft_DotNet_Framework_4_V1R4_STIG_SCAP_1-1_Benchmark-xccdf.xml---MAC-2_Classified-1">
            <cdf:benchmark href="U_Microsoft_DotNet_Framework_4_V1R4_STIG_SCAP_1-1_Benchmark-xccdf.xml"></cdf:benchmark>
            <cdf:organization>SPAWAR Systems Center Atlantic</cdf:organization>
            <cdf:identity privileged="true" authenticated="true">CCSAdmin</cdf:identity>
            <cdf:profile idref="MAC-2_Classified"></cdf:profile>
            <cdf:target>hostname</cdf:target>
            <cdf:target-address>192.168.1.000</cdf:target-address>
            <cdf:target-facts>
                  <cdf:fact name="urn:scap:fact:asset:identifier:host_name" type="string">hostname</cdf:fact>
                  <cdf:fact name="urn:scap:fact:asset:identifier:domain" type="string">.net</cdf:fact>
                  <cdf:fact name="urn:scap:fact:asset:identifier:fqdn" type="string">hostname.net</cdf:fact>
                  <cdf:fact name="urn:scap:fact:asset:identifier:os_name" type="string">Windows 7 Enterprise</cdf:fact>
                  <cdf:fact name="urn:scap:fact:asset:identifier:os_service_pack" type="string">Service Pack 1</cdf:fact>
                  <cdf:fact name="urn:scap:fact:asset:identifier:ipv4" type="string">192.168.1.000</cdf:fact>
            </cdf:target-facts>
            <cdf:platform idref="cpe:/a:microsoft:.net_framework:4.0"></cdf:platform>
            <cdf:rule-result version="APPNET0031" time="2016-07-20T11:59:59" idref="SV-7438r2_rule" weight="10.0" severity="medium">
                  <cdf:result>pass</cdf:result>
                  <cdf:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
                        <cdf:check-content-ref href="U_Microsoft_DotNet_Framework_4_V1R4_STIG_SCAP_1-1_Benchmark-oval.xml" name="oval:mil.disa.fso.dotnet:def:2"></cdf:check-content-ref>
                  </cdf:check>
             </cdf:rule-result>
            <cdf:rule-result version="APPNET0046" time="2016-07-20T11:59:59" idref="SV-7444r3_rule" weight="10.0" severity="medium">
                  <cdf:result>fail</cdf:result>
                  <cdf:fix id="F-12602r12_fix"></cdf:fix>
                  <cdf:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
                        <cdf:check-content-ref href="U_Microsoft_DotNet_Framework_4_V1R4_STIG_SCAP_1-1_Benchmark-oval.xml" name="oval:mil.disa.fso.dotnet:def:15"></cdf:check-content-ref>
                  </cdf:check>
            </cdf:rule-result>
      </cdf:TestResult>
</cdf:Benchmark>

我更改了查询,现在都如下所示:

var findingDetails = from f in element.Elements(ns + "Group")
                                 select new
                                 {
                                     idrefStatus = (string)"",
                                     result = (string)"",
                                     dateTime = (string)"",
                                     testID = (string)f.Attribute("id").Value,
                                     title = (string)f.Element(ns + "title"),
                                     idref = (string)f.Element(ns + "Rule").Attribute("id").Value,
                                     severity = (string)f.Element(ns + "Rule").Attribute("severity").Value,
                                     description = (string)f.Element(ns + "Rule").Element(ns + "description"),
                                     fixText = (string)f.Element(ns + "Rule").Element(ns + "fixtext")                                         
                                 };
            var getStatus = from gs in element.Descendants(ns + "rule-result")
                            select new
                            {
                                idrefStatus = (string)gs.Attribute("idref").Value,
                                result = (string)gs.Element(ns + "result"),
                                dateTime = (string)gs.Attribute("time"),
                                testID = (string)"",
                                title = (string)"",
                                idref = (string)"",
                                severity = (string)"",
                                description = (string)"",
                                fixText = (string)""
                            };

 var combined = findingDetails.Concat(getStatus);

但是现在的输出是这样的

foreach (var cf in combined)
{
     Console.WriteLine(cf.idref + ", " + cf.result);
}

SV-7438r2_rule, 
SV-7444r3_rule, 
SV-40966r1_rule, 
SV-41075r1_rule, 
, pass
, fail
, pass
, pass

然而,我试图得到这样的东西:

SV-7438r2_rule, pass
SV-7444r3_rule, fail
SV-40966r1_rule, pass
SV-41075r1_rule, pass

【问题讨论】:

  • 类型不匹配......除了将序列转换为objectdynamic 之外,它们应该如何连接?请阅读:msdn.microsoft.com/en-us/library/bb397696.aspx 因为匿名类型的 Equals 和 GetHashCode 方法是根据属性的 Equals 和 GetHashCode 方法定义的,所以相同匿名类型的两个实例只有在它们的所有属性都相等时才相等。
  • 您是要合并它们而不是连接它们吗?您不能连接两个不同类型的集合。
  • 当然可以连接匿名类型的集合,但前提是它们具有所有相同的字段(类型和名称)。你的没有。您甚至希望如何连接它们?您希望结果是什么?
  • @AntP,我考虑过.Merge(),但对于findingDetails,它并没有以智能方式出现...
  • @Chris - 如果你解释一下你想要做的事情背后的动机,我们可以提供帮助

标签: c# linq concatenation ienumerable


【解决方案1】:

根据您的预期输出(“然而,我正在尝试获得类似这样的内容:...”)和您添加的数据,您正在寻找的似乎是 join而不是concat 列表(concat 会给你 n*m 条记录)

这似乎是您正在寻找的:

 XNamespace ns = "http://checklists.nist.gov/xccdf/1.1";
 var findingDetails = (from f in XDocument.Load("data.xml").Descendants(ns + "Group")
                       let rule = f.Element(ns + "Rule")
                       select new
                       {
                          testID = (string)f.Attribute("id").Value,
                          title = (string)f.Element(ns + "title"),
                          idref = (string)rule.Attribute("id").Value,
                          severity = (string)rule.Attribute("severity").Value,
                          description = (string)rule.Element(ns + "description"),
                          fixText = (string)rule.Element(ns + "fixtext")
                       }).ToList();
 var getStatus = (from gs in XDocument.Load("data.xml").Descendants(ns + "rule-result")
                  select new
                  {
                     idrefStatus = (string)gs.Attribute("idref").Value,
                     result = (string)gs.Element(ns + "result"),
                     dateTime = (string)gs.Attribute("time"),
                  }).ToList();

 var result = (from d in findingDetails
               join f in getStatus on d.idref equals f.idrefStatus
               select new { d, f }).ToList();

如果您的 Groups 可能没有匹配的 rule-result,请改用 left join

【讨论】:

  • 吉拉德,谢谢!再次。一直忙于学习所有这些东西。
  • @Chris - 很高兴能帮上忙 :)
  • 您可以通过执行类似let rule = f.Element(ns + "Rule") 然后idref = (string)rule.Attribute("id").Value 之类的操作来稍微优化一下以避免重复查找Rule
【解决方案2】:

如果声明的两个匿名类型具有完全相同的属性,则可以连接它们。

你不能连接两种不同的类型,但你可以将它们转换为object,然后连接:

List<int> ints = new List<int>() { 1, 2, 3 };
List<string> strings = new List<string> { "a", "b", "c" };

ints.Cast<object>().Concat( strings.Cast<object>() );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多