如何让 LINQ-to-XML 中的动态 WHERE 语句发挥作用?

发布于 2024-07-24 18:40:28 字数 2820 浏览 6 评论 0原文

这个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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南冥有猫 2024-07-31 18:40:28

我希望您的意思是:

public List<SmartForm> GetSmartForms(
       XDocument xmlDoc, Func<XElement,bool> whereClause)

and:

Func<XElement, bool> whereClause = smartForm => (int)smartForm.Element("id") == id;

要用作方法,我会将其设为 IEnumerable:

public static IEnumerable<SmartForm> GetSmartForms(
       XDocument xmlDoc, Func<XElement,bool> predicate)
    {
        return xmlDoc.Descendants("smartForm")
            .Where(predicate)
            .Select(smartForm => new SmartForm
            {
                ... snip
            });
    }

并调用为:

            foreach (SmartForm smartForm in GetSmartForms(xmlDoc,
                sf => (int)sf.Element("id") == id))
            {
                _collection.Add(smartForm);
            }

I expect you mean:

public List<SmartForm> GetSmartForms(
       XDocument xmlDoc, Func<XElement,bool> whereClause)

and:

Func<XElement, bool> whereClause = smartForm => (int)smartForm.Element("id") == id;

To use as a method, I would make it IEnumerable<T>:

public static IEnumerable<SmartForm> GetSmartForms(
       XDocument xmlDoc, Func<XElement,bool> predicate)
    {
        return xmlDoc.Descendants("smartForm")
            .Where(predicate)
            .Select(smartForm => new SmartForm
            {
                ... snip
            });
    }

and call as:

            foreach (SmartForm smartForm in GetSmartForms(xmlDoc,
                sf => (int)sf.Element("id") == id))
            {
                _collection.Add(smartForm);
            }
夏了南城 2024-07-31 18:40:28

我只是没有领悟 lambda 魔法,

马克的回答解决了您遇到的情况。 我的回答将尝试解决您所缺少的 lambda 魔法。

lambda 表达式由三个部分组成: 参数 arrow methodbody

Func<int, int, int> myFunc =  (x, i) => x * i ;

对于参数,除单个参数外,这些参数必须括在括号中。 本节将变量名称引入作用域。 由于您没有在 lambda 中提供参数,因此没有任何变量名称。

箭头 是必需的,因为您没有箭头,编译器不知道您正在创建 lambda。

对于方法体,如果它是一行,则隐含返回。 否则,打开大括号并像平常一样创建方法体。

I'm just not grokking the lambda magic,

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

Func<int, int, int> myFunc =  (x, i) => x * i ;

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文