Как я могу заставить этот динамический оператор WHERE в моем LINQ-to-XML работать? - PullRequest
0 голосов
/ 10 июня 2009

В этот вопрос Джон Скит предложил очень интересное решение для создания динамического оператора LINQ-to-XML, но мои знания о лямбдах и делегатах еще недостаточно развиты для реализации это:

У меня есть пока , но, конечно, я получаю ошибку "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);

У меня так далеко, но Я просто не умею ламбда-магию , как мне это сделать?

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")
                     });
}

Ответы [ 2 ]

3 голосов
/ 10 июня 2009

Я ожидаю, что вы имеете в виду:

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

и

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

Чтобы использовать в качестве метода, я бы сделал это IEnumerable<T>:

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);
            }
1 голос
/ 10 июня 2009

Я просто не ловлю лямбда-магию,

Ответ Марка касается вашего сценария. В моем ответе я попытаюсь разобраться с лямбда-магией, которой вам не хватает.

Лямбда-выражения состоят из трех частей: параметры arrow methodbody

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

Для параметров они должны быть заключены в скобки, за исключением случая использования одного параметра. Этот раздел вводит имена переменных в область видимости. Поскольку вы не указали параметры в своей лямбде, у вас не было имен переменных.

стрелка требуется, так как у вас не было стрелки, компилятор не знал, что вы делаете лямбду.

Для methodbody , если это однострочный, подразумевается возврат. В противном случае откройте фигурную скобку и создайте тело метода, как обычно.

...