2010-11-17 3 views
5

Я ищу способ разбора условного выражения на строку.Условные выражения для строковых выражений

Лучший пример, который я могу придумать, это LINQ-to-SQL. Он использует ExpressionVisitors для форматирования предложений «Где». Пример:

from a in b where a.x == 5 && a.y < 3 select a 

Это было бы перевести на следующую строку (примерно, MSSQL не тока для меня):

"SELECT * FROM b WHERE x = 5 AND y < 3" 

Из того, что я читал, это было сделано с помощью класса ExpressionVisitor, а объясняется в этой статье: http://blogs.msdn.com/b/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspx

Теперь проблема в том, что я не использую LINQ, но мне нужна эта конкретная функциональность. Есть ли способ разбора такого состояния? Я готов сделать что-нибудь с отражением, делегатов, лямбда и т.д.

Честно говоря, я не думаю, что это возможно, но мой мозг немного обжаренные (читай: хорошо, если вопрос смешно) , поэтому я решил, что могу просто дать S/O попробовать.

EDIT: Заключительный пример использования:

// Usage: 
foo.Bar(foo => foo.X == 5 && foo.Y < 3) 

// Ideal string output (variable name (foo) is not needed): 
"foo.X == 5 && foo.Y < 3" 

EDIT 2: Да, число может быть меньше 3 и равно 5. Рассказал вам мой мозг жарится.

+0

LINQ к SQL делает именно это. Если вы напишете свое собственное, вы бы пересмотрели LINQ-to-SQL, который уже существует - это кажется бессмысленным усилием. (Тем не менее, люди это сделали, например, Google для IQToolkit.) Вы сказали: «Я не использую LINQ», но ваш код говорит об обратном (он полон LINQ; деревья выражений считаются частью LINQ). – Timwi

ответ

4

Если речь идет о создании самого дерева выражений, то вы можете использовать возможности компилятора C#.

Допустимо использовать выражение лямбда для выражения функции Expression>, если известны аргументы типа Func. Например

private static void PrintExpression(Expression<Func<int, bool>> lambda) 
{ 
     Console.WriteLine(lambda.ToString()); 
} 

можно назвать

PrintExpression(a=> a > 0 && a < 5); 

Вы можете импровизировать с обобщениями, как

private static void PrintExpression<T1,T2>(Expression<Func<T1, T2>> lambda) 
{ 
     Console.WriteLine(lambda.ToString()); 
} 

и называя его

PrintExpression<int, bool>(a=> a > 0 && a < 5); 

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

Помните, что выражение лямбда скомпилировано в выражение во время компиляции - поэтому он не может подставить его уже скомпилированным Func.

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

3

попробовать что-то вроде этого:

static string GetExpressionString<T>(Expression<Func<T, bool>> expression) 
{ 
    return expression.Body.ToString(); 
} 

Использование в качестве так:

string s = GetExpressionString<Foo>(foo => foo.X == 5 && foo.Y < 3); 

который будет возвращать:

((foo.X = 5) && (foo.Y < 3)) 
+0

О, вау, я клянусь, что ответ мхо не был здесь, когда я разместил мой! Он немного глубже, но я останусь здесь, наверное. – MatthewKing

+0

Я хотел бы добавить, что удаление любой сильной типизации и разрешение «объекта» было бы намного более полезным. :) – Lazlo

Смежные вопросы