Как лучше всего сделать оператор LINQ-to-XML динамическим?

Я загружаю данные XML в объект с помощью этого оператора LINQ:

var smartFormFields = from smartFormField in xmlDoc.Descendants("smartFormField")
                      select new Models.SmartFormField
                      {
                          IdCode = smartFormField.Element("idCode").Value,
                          Label = smartFormField.Element("label").Value,
                          FieldType = smartFormField.Element("fieldType").Value,
                          DisplayStatus = smartFormField.Element("displayStatus").Value,
                          RequiredStatus = smartFormField.Element("requiredStatus").Value,
                          DisplayColumn = (int)smartFormField.Element("displayColumn"),
                          DisplayOrder = (int)smartFormField.Element("displayOrder"),
                          Description = smartFormField.Element("description").Value,
                          Example = smartFormField.Element("example").Value,
                          ControlType = smartFormField.Element("controlType").Value,
                          AutoSuggestDataSource = smartFormField.Element("autoSuggestDataSource").Value
                      };

Однако мой оператор WHERE (и ORDERBY) будет меняться каждый раз, например,

может быть это:

var smartFormFields = from smartFormField in xmlDoc.Descendants("field")
                      where smartFormField.Element("IdCode").Value == "lastName"
                      select new Models.SmartFormField
                      {...

может быть это:

var smartFormFields = from smartFormField in xmlDoc.Descendants("field")
                      where (int)smartFormField.Element("DisplayOrder").Value > 50
                      select new Models.SmartFormField
                      {...

и т.п.

Как поместить оператор Where в переменную, например так:

ПСЕВДО-КОД:

string whereStatement = "where (int)smartFormField.Element(\"DisplayOrder\").Value > 50";

var smartFormFields = from smartFormField in xmlDoc.Descendants("field")
                      &&whereStatement
                      select new Models.SmartFormField
                      {...

person Edward Tanguay    schedule 09.06.2009    source источник


Ответы (1)


Вы должны выразить это как строку? Если вы готовы предоставить его в качестве делегата, вы можете использовать:

// Just as one example of a where clause
Func<XElement, bool> whereClause = sff => (int) sff.Element("DisplayOrder").Value > 50;

var smartFormFields = xmlDoc.Descendants("field")
                            .Where(whereClause)
                            .Select(sff => 
                                new Models.SmartFormField
                                {
                                    IdCode = sff.Element("idCode").Value,
                                    ...
                                });

Если вы поместите это в метод, вам просто нужно использовать лямбда-выражение:

var fields = GetFormFields(sff => (int) sff.Element("DisplayOrder").Value > 50);

так далее

Это позволит вам легко указывать разные значения для разных вызовов, но вы не сможете просто поместить выражения в текстовый файл без дополнительной работы. Каковы ваши реальные требования здесь? Не могли бы вы сопоставить «имя фильтра» с Func<XElement, bool>, а затем прочитать имена фильтров во время выполнения? Или вам действительно нужно, чтобы он полностью контролировался во время выполнения произвольным образом?

(Обратите внимание, что порядок аналогичен, но, вероятно, немного сложнее... давайте сначала отсортируем фильтрацию.)

person Jon Skeet    schedule 09.06.2009
comment
очень интересно, требования таковы: иметь возможность анализировать различные коды загрузки из конструктора для загрузки различных групп из XML-файла, поэтому у меня будет просто оператор switch, который преобразует текст в делегаты, пусть build попытается построить это в... - person Edward Tanguay; 09.06.2009
comment
Я бы просто использовал Dictionary‹string, Func‹XElement, bool›› и использовал его, а не оператор switch. - person Jon Skeet; 09.06.2009
comment
хотя это не мой пост, но все же я хотел бы попросить вас опубликовать полный небольшой рабочий пример использования строки в LINQ, например xmlDoc.Descendants("field") .Where(whereClause) - person Thomas; 21.07.2015
comment
@Thomas: Ну, что еще тебе нужно, кроме того, что есть? ... будет просто лямбда-выражением. - person Jon Skeet; 21.07.2015
comment
where delegate function code не завершен. мне нужно посмотреть, как будет выглядеть код делегата where .. потому что я не знаком с таким предложением where. Спасибо - person Thomas; 22.07.2015
comment
@Thomas: Ну, в последней части показан пример ... но я изменил ... на пример лямбда-выражения ... - person Jon Skeet; 22.07.2015
comment
спасибо, мы могли бы написать так все это... тогда почему вы используете функцию делегата как отдельную... была ли какая-то особая причина? var smartFormFields = xmlDoc.Descendants("field") .Where(e=> e.Element("DisplayOrder").Value > 50) .Select(sff => new Models.SmartFormField { IdCode = sff.Element("idCode").Value, ... }); - person Thomas; 22.07.2015
comment
@Thomas: Дело в том, что OP хочет передать делегата в метод или, возможно, выбрать между несколькими различными вариантами в одном и том же методе. - person Jon Skeet; 22.07.2015
comment
@JonSkeet Спасибо за ответ :) - person Thomas; 22.07.2015