2010-11-17 17 views
5

Estoy buscando una manera de analizar una expresión condicional a una cadena.Analizando Expresiones Condicionales a la Cadena

El mejor ejemplo que puedo pensar es LINQ-to-SQL. Utiliza ExpressionVisitors para formatear cláusulas "Dónde". Ejemplo:

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

Eso se traduciría en la siguiente cadena (aproximadamente, MSSQL actual no es para mí):

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

Por lo que he leído, esto se hizo utilizando la clase ExpressionVisitor, como Explicado en este artículo: http://blogs.msdn.com/b/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspx

Ahora el problema es que no uso LINQ, pero necesito esta funcionalidad en particular. ¿Hay alguna manera de analizar una condición como esa? Estoy dispuesto a hacer cualquier cosa con la reflexión, los delegados, lambda, etc.

Honestamente, no creo que sea posible, pero mi cerebro es un poco frito (es decir: bueno si la pregunta es ridícula) , así que pensé que podría darle una oportunidad a S/O.

EDITAR: ejemplo de uso final:

// 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: Sí, un número puede ser inferior al 3 e igual a 5. Te dije que mi cerebro está frito.

+0

LINQ a SQL hace exactamente esto. Si escribes el tuyo, estarías reimplantando LINQ-to-SQL, que ya existe, eso parece un esfuerzo sin sentido. (Sin embargo, la gente lo ha hecho, google para IQToolkit, por ejemplo). Dijo "No uso LINQ", pero su código dice lo contrario (está lleno de LINQ; los árboles de expresión se consideran parte de LINQ). – Timwi

Respuesta

4

Si se trata de construir el árbol de expresiones en sí, entonces podría aprovechar las capacidades del compilador de C#.

Es legal pasar una expresión lambda a una aceptación de función una Expresión>, siempre que se conozcan los argumentos de tipo de Func. Por ejemplo

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

puede ser llamado como

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

Puede improvisar con los genéricos como

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

y llamándolo con

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

para la impresión personalizada de la expresión parte, puedes escribir como Implemente la función recursiva que imprime una expresión o cualquier otra lógica que le convenga.

Recuerde, la expresión lambda se compila en una Expresión en tiempo de compilación, por lo que no puede subsituarla con el Func ya compilado.

Como alternativa a esto, siempre puede crear un proveedor de consultas personalizado, pero eso se desviaría ligeramente del propósito, ya que tendría que vincularlo como un tipo de consulta (personalizado de nuevo).

3

intentar algo como esto:

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

uso como tan:

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

que devolverá:

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

¡Oh, vaya! ¡Juro que la respuesta de mho no estaba aquí cuando publiqué la mía! El suyo es un poco más profundo, pero creo que dejaré el mío aquí. – MatthewKing

+0

Me gustaría agregar que eliminar cualquier tipeo fuerte y permitir "objeto" sería mucho más útil. :) – Lazlo

Cuestiones relacionadas