如何让 LINQ-to-XML 中的动态 WHERE 语句发挥作用?
在这个Jon Skeet 提供了一个非常有趣的解决方案来使 LINQ-to-XML 语句动态化,但我对 lambda 和委托的了解还不够先进,无法实现它:
我已经它到目前为止,但当然我收到错误“smartForm在当前上下文中不存在”:
private void LoadWithId(int id)
{
XDocument xmlDoc = null;
try
{
xmlDoc = XDocument.Load(FullXmlDataStorePathAndFileName);
}
catch (Exception ex)
{
throw new Exception(String.Format("Cannot load XML file: {0}", ex.Message));
}
Func<XElement, bool> whereClause = (int)smartForm.Element("id") == id";
var smartForms = xmlDoc.Descendants("smartForm")
.Where(whereClause)
.Select(smartForm => new SmartForm
{
Id = (int)smartForm.Element("id"),
WhenCreated = (DateTime)smartForm.Element("whenCreated"),
ItemOwner = smartForm.Element("itemOwner").Value,
PublishStatus = smartForm.Element("publishStatus").Value,
CorrectionOfId = (int)smartForm.Element("correctionOfId"),
IdCode = smartForm.Element("idCode").Value,
Title = smartForm.Element("title").Value,
Description = smartForm.Element("description").Value,
LabelWidth = (int)smartForm.Element("labelWidth")
});
foreach (SmartForm smartForm in smartForms)
{
_collection.Add(smartForm);
}
}
理想情况下我希望能够说:
var smartForms = GetSmartForms(smartForm=> (int) smartForm.Element("DisplayOrder").Value > 50);
我已经到目前为止,但是我只是没有掌握 lambda 魔法,我该怎么做?
public List<SmartForm> GetSmartForms(XDocument xmlDoc, XElement whereClause)
{
var smartForms = xmlDoc.Descendants("smartForm")
.Where(whereClause)
.Select(smartForm => new SmartForm
{
Id = (int)smartForm.Element("id"),
WhenCreated = (DateTime)smartForm.Element("whenCreated"),
ItemOwner = smartForm.Element("itemOwner").Value,
PublishStatus = smartForm.Element("publishStatus").Value,
CorrectionOfId = (int)smartForm.Element("correctionOfId"),
IdCode = smartForm.Element("idCode").Value,
Title = smartForm.Element("title").Value,
Description = smartForm.Element("description").Value,
LabelWidth = (int)smartForm.Element("labelWidth")
});
}
In this question Jon Skeet offered a very interesting solution to making a LINQ-to-XML statement dynamic, but my knowledge of lambdas and delegates is not yet advanced enough to implement it:
I've got it this far, but of course I get the error "smartForm does not exist in the current context":
private void LoadWithId(int id)
{
XDocument xmlDoc = null;
try
{
xmlDoc = XDocument.Load(FullXmlDataStorePathAndFileName);
}
catch (Exception ex)
{
throw new Exception(String.Format("Cannot load XML file: {0}", ex.Message));
}
Func<XElement, bool> whereClause = (int)smartForm.Element("id") == id";
var smartForms = xmlDoc.Descendants("smartForm")
.Where(whereClause)
.Select(smartForm => new SmartForm
{
Id = (int)smartForm.Element("id"),
WhenCreated = (DateTime)smartForm.Element("whenCreated"),
ItemOwner = smartForm.Element("itemOwner").Value,
PublishStatus = smartForm.Element("publishStatus").Value,
CorrectionOfId = (int)smartForm.Element("correctionOfId"),
IdCode = smartForm.Element("idCode").Value,
Title = smartForm.Element("title").Value,
Description = smartForm.Element("description").Value,
LabelWidth = (int)smartForm.Element("labelWidth")
});
foreach (SmartForm smartForm in smartForms)
{
_collection.Add(smartForm);
}
}
Ideally I want to be able to just say:
var smartForms = GetSmartForms(smartForm=> (int) smartForm.Element("DisplayOrder").Value > 50);
I've got it this far, but I'm just not grokking the lambda magic, how do I do this?
public List<SmartForm> GetSmartForms(XDocument xmlDoc, XElement whereClause)
{
var smartForms = xmlDoc.Descendants("smartForm")
.Where(whereClause)
.Select(smartForm => new SmartForm
{
Id = (int)smartForm.Element("id"),
WhenCreated = (DateTime)smartForm.Element("whenCreated"),
ItemOwner = smartForm.Element("itemOwner").Value,
PublishStatus = smartForm.Element("publishStatus").Value,
CorrectionOfId = (int)smartForm.Element("correctionOfId"),
IdCode = smartForm.Element("idCode").Value,
Title = smartForm.Element("title").Value,
Description = smartForm.Element("description").Value,
LabelWidth = (int)smartForm.Element("labelWidth")
});
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我希望您的意思是:
and:
要用作方法,我会将其设为 IEnumerable:
并调用为:
I expect you mean:
and:
To use as a method, I would make it
IEnumerable<T>
:and call as:
马克的回答解决了您遇到的情况。 我的回答将尝试解决您所缺少的 lambda 魔法。
lambda 表达式由三个部分组成: 参数 arrow methodbody
对于参数,除单个参数外,这些参数必须括在括号中。 本节将变量名称引入作用域。 由于您没有在 lambda 中提供参数,因此没有任何变量名称。
箭头 是必需的,因为您没有箭头,编译器不知道您正在创建 lambda。
对于方法体,如果它是一行,则隐含返回。 否则,打开大括号并像平常一样创建方法体。
Marc's answer addresses the scenario you have. My answer will attempt to address the lambda magic you are missing.
lambda expressions have three parts: parameters arrow methodbody
For parameters, these must be enclosed in parens except in the case of a single parameter. This section introduces variable names into the scope. Since you didn't supply parameters in your lambda, you didn't have any variable names.
arrow is required, since you didn't have an arrow, the compiler didn't know you were making a lambda.
For methodbody, if it's a one-liner, return is implied. Otherwise, open a curly brace and make a method body like you normally would.