我正在处理一组函数,其中一个是解析XML文件,并返回与我所拥有的基于属性的条件匹配的元素。
这是我必须使用的XML示例:
<rs:insert>
<z:row Inst='AM5001' Event='EventA' HostName='HostA' EventType='NORMAL' TXID='0000003327'/>
<z:row Inst='AM5001' Event='EventB' HostName='HostB' EventType='NORMAL' TXID='0000011173'/>
<z:row Inst='AM4067' Event='EventA' HostName='HostA' EventType='NORMAL' TXID='0000011175'/>
<z:row Inst='AM5546' Event='EventC' HostName='HostC' EventType='NORMAL' TXID='0000011177'/>
<z:row Inst='AM4567' Event='EventQ' HostName='HostD' EventType='NORMAL' TXID='0000011593'/>
这是我到目前为止的一小部分:
internal protected IEnumerable<XElement> GetElement(XDocument oXMLDoc
, List<KeyValuePair<string, string>> SearchCriteria)
{
var vElementQuery = oXMLDoc.Elements()
.Where(e => SearchCriteria.ForEach(sc => e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()))
.Select(e => e);
foreach (var xElement in vElementQuery)
{
yield return xElement;
}
}
我在vElementQuery的where子句中遇到错误:
仅分配,调用,增量,减量,等待和新对象 表达式可以用作语句
简单来说,我会根据Inst和Event进行查询,但偶尔我也需要基于hostname和Eventtype。
基本上,我不知道我需要匹配多少属性条件,所以我想将它们作为列表或数组添加,认为KeyValuePair
会很有用,因为它给了我我需要的名称和比较(价值)。
感谢任何帮助。
答案 0 :(得分:1)
Where
需要一个谓词:一个e
(在这种情况下为XElement
)并返回bool
的函数。
相反,您尝试返回SearchCriteria.ForEach()
的结果,返回void
。它所做的就是迭代集合并为每个项目调用void
lambda。因此,您不能将它用作谓词的主体。修复此问题后,这将是您的下一个问题,但同样的修复工具会解决这两个问题。
.Where(e =>
SearchCriteria.ForEach(sc =>
e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()
)
)
由于ForEach
返回void
,因此需要返回void
的lambda。函数体必须是一个声明。在lambda中,如果返回类型不是void
,并且正文是表达式,则返回该表达式的结果 - 将其称为隐式返回语句。但是这里的返回值是无效的 - 由the parameter type of ForEach
确定:
public void ForEach(
Action<T> action
)
Action<T>
有一个参数,没有返回类型。无论编译器使用什么推理规则,都会假设你正在尝试编写一个void lambda,而不是你试图给ForEach
一个谓词。
这是你给它的lambda的主体:
e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()
如果没有编译器在其前面提供隐式return
,那么这不是一个声明。这是一种表达方式。作为声明,它不是合法的C#。尝试编译:
1 != 2;
同样的错误。 C或Perl不会关心,但C#会这样做。
我认为您可能需要Any
而不是ForEach
:
.Where(e =>
SearchCriteria.Any(sc =>
e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()
)
)
也就是说,返回任何搜索条件与其任何属性匹配的任何e
。 Any
获取谓词并返回bool
,修复这两个错误。