Есть ли способ, которым я могу динамически определить тело предиката из строки, содержащей код? - PullRequest
3 голосов
/ 19 февраля 2009

Это, вероятно, глупый вопрос, но здесь идет. Я хотел бы иметь возможность динамически создавать предикат из строки, анализируемой из столбца VARCHAR базы данных, или любой строки, в этом отношении. Например, скажем, столбец в базе данных содержал следующую строку:

return e.SomeStringProperty.Contains("foo");

Эти кодовые / строковые значения будут храниться в базе данных, зная, каковы возможные свойства универсального "e", и зная, что они должны возвращать логическое значение. Затем в волшебном, чудесном, фантастическом мире код мог выполняться, не зная, что такое предикат, например:

string predicateCode = GetCodeFromDatabase();
var allItems = new List<SomeObject>{....};
var filteredItems = allItems.FindAll(delegate(SomeObject e) { predicateCode });

или лямбдаизированный:

var filteredItems = allItems.FindAll(e => [predicateCode]);

Я знаю, что, вероятно, никогда не будет так просто, но есть ли способ, возможно, с помощью Reflection.Emit, динамически создавать код делегата из текста и передавать его FindAll (или любому другому анонимному / расширению) метод?

Ответы [ 4 ]

1 голос
/ 19 февраля 2009

Компиляторы C # и VB доступны в .NET Framework:

C # Поставщик CodeDom

Имейте в виду, что таким образом вы получите отдельную сборку (которую можно выгружать, только если она находится в отдельном домене приложений). Такой подход возможен только в том случае, если вы можете собрать все предикаты, которые вам понадобятся одновременно. В противном случае слишком много накладных расходов.

System.Reflection.Emit - отличный API для динамического генерирования кода для CLR. Однако, это немного громоздко в использовании, и вы должны изучить CIL.

Деревья выражений LINQ - это простой в использовании бэкэнд (компиляция в CIL), но вам придется написать собственный синтаксический анализатор.

Я предлагаю вам взглянуть на один из «динамических языков», работающих на CLR (или DLR), например IronPython . Это самый эффективный способ реализовать эту функцию, если вы спросите меня.

1 голос
/ 19 февраля 2009

Проверьте проект Dynamic Linq, он делает все это и даже больше!

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Отлично подходит для простых вещей, таких как выбранные пользователем команды orderby или where

0 голосов
/ 03 июля 2009

Я вышел из динамического linq, потому что он ограничен в способах поиска в коллекции, если только вы не докажете, что я не прав.

Мой фильтр должен быть следующим: в списке заказов отфильтруйте список так, чтобы у меня были только заказы в коллекции предметов в этом заказе, элемент с именем «кока-кола».

Так что это приведет к методу: orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"))

В динамическом linq я не нашел способа сделать это, поэтому я начал с CodeDomProvicer. Я создал новый Type с методом, который содержит мой динамически построенный FindAll Метод:

public static IList Filter(list, searchString)
{
   // this will by dynamically built code
   return orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"));
}

когда я пытаюсь собрать эту сборку:

CompilerResults results = provider.CompileAssemblyFromSource(parameters, sb.ToString());

Я получаю сообщение об ошибке:

Invalid expression term ">"

Почему компилятор не может скомпилировать предикат?

0 голосов
/ 19 февраля 2009

Можно использовать emit , но вы будете создавать свой собственный парсер.

EDIT

Я помню, что в лейтмотиве ScottGu для PDC он показал функцию, использующую CLI-версию .net framework, которая напоминала eval Руби, но я не могу найти URL, который это подтвердил бы. Я делаю это вики-сообществом, чтобы любой, у кого есть хорошая ссылка, мог добавить его.

...