create c# expression-trees

c# - create - variable '''' de tipo '''' referenciada desde el alcance '''', pero no está definida



lambda c# (3)

Como se indica en la otra respuesta, tiene dos expresiones donde ambas tienen un parámetro llamado y . Los que no se relacionan automáticamente entre sí.

Para compilar correctamente su expresión, debe especificar los parámetros de ambas expresiones de origen:

Expression<Func<string, bool>> e1 = (y => y.Length > 0); Expression<Func<string, bool>> e2 = (y => y.Length < 5); var e3 = Expression.And(e1.Body, e2.Body); // (string, string) by adding both expressions'' parameters. var e4 = Expression.Lambda<Func<string, string, bool>>(e3, new[] { e1.Parameters[0], e2.Parameters[0] }); Func<string, string, bool> compiledExpression = e4.Compile(); bool result = compiledExpression("Foo", "Foo");

Por supuesto, querrá una expresión que combine ambas expresiones con un solo parámetro. Puedes reconstruir las expresiones así:

ParameterExpression param = Expression.Parameter(typeof(string), "y"); var lengthPropertyExpression = Expression.Property(param, "Length"); var e1 = Expression.GreaterThan(lengthPropertyExpression, Expression.Constant(0)); var e2 = Expression.LessThan(lengthPropertyExpression, Expression.Constant(5)); var e3 = Expression.AndAlso(e1, e2); var e4 = Expression.Lambda<Func<string, bool>>(e3, new[] { param }); Func<string, bool> compiledExpression = e4.Compile(); bool result = compiledExpression("Foo");

En cuanto a su comentario, no desea reconstruir la expresión, sino hacerlo en el cuerpo y los parámetros de una expresión existente: esto funciona usando ExpressionRewriter de Combinar dos expresiones lambda en c # y AndAlso de Reemplazar el nombre del parámetro en el Cuerpo de una Expresión :

Expression<Func<string, bool>> e1 = (y => y.Length > 0); Expression<Func<string, bool>> e2 = (z => z.Length < 10); var e3 = ParameterReplacer.AndAlso<string>(e1, e2); Func<string, bool> compiledExpression = e3.Compile(); bool result = compiledExpression("Foo");

Bueno, el siguiente código es autoexplicativo; Quiero combinar dos expresiones en una utilizando el operador And . La última línea causa un error en el tiempo de ejecución:

Información adicional: variable ''y'' de tipo ''System.String'' referenciada desde el alcance '''', pero no está definida

Código:

Expression<Func<string, bool>> e1 = y => y.Length < 100; Expression<Func<string, bool>> e2 = y => y.Length < 200; var e3 = Expression.And(e1.Body, e2.Body); var e4 = Expression.Lambda<Func<string, bool>>(e3, e1.Parameters.ToArray()); e4.Compile(); // <--- causes run-time error


El problema es que los objetos de expresión de parámetros que representan la variable y en las expresiones e1 y e2 son diferentes. El hecho de que las dos variables tengan el mismo nombre y el mismo tipo no importa: e1.Parameters.First() y e2.Parameters.First() no es el mismo objeto.

Esto causa el problema que ve: solo el parámetro e1 de e1 está disponible para Lambda<> , mientras que el parámetro e2 de e2 está fuera de alcance.

Para solucionar este problema, use las API de Expression para crear e1 y e2 . De esta manera usted podría compartir la expresión de parámetros a través de ellos, eliminando así el problema de alcance.


Gracias a todos colaboraron.

Como ha señalado dasblinkenlight , los dos parámetros en las dos expresiones no son los mismos. ¿Razón? Bueno, es el truco del compilador. Al compilar, crea una clase para cada expresión y nombra cada parámetro algo así como xxx1, xxx2, ... completamente diferente de los nombres originales.

Y la respuesta para .Net 4.0+:

Cómo combinar dos lambdas