2010-08-19 14 views
6

Tengo dos árboles de expresión definidos como esto:Pasando un árbol de expresión como un parámetro a otro árbol de expresión

private Expression<Func<TEntity, TPropertyResult>> PropertyAccessor { get; set; } 

y

private Expression<Func<TPropertyResult, bool>> TestExpression { get; set; } 

Necesito crear un nuevo árbol de expresión que dará lugar a el equivalente de:

var expression = p => this.TestExpression(this.PropertyAccessor(p)); 

al utilizar Expression.Invoke(this.TestExpression, this.PropertyAccessor), me sale el siguiente error

{"Expression of type 'System.Func`2[MyEntity,System.String]' cannot be used for parameter of type 'System.String'"}

TPropertyResult es una cadena durante mi prueba.

Intenté usar Expression.Call o Expression.Invoke. Sin suerte. ¿Qué debería usar?

+0

¿Cuál fue el error del compilador? Además, el código no es tan legible. ¿Estás seguro de que las cosas de .Net 2.0 no son suficientes para lo que quieres lograr? –

+0

Al usar Invoke, dice: '{" Expresión de tipo 'System.Func'2 [MyEntity, System.String]' no se puede utilizar para el parámetro de tipo 'System.String' "}'. Ahí es cuando trato de especificar una cadena como 'TPropertyResult', pero el problema no está limitado a una cadena. –

Respuesta

7

creo que esto hace lo que está pidiendo:

Expression<Func<TEntity, bool>> Combined 
{ 
    get 
    { 
     var entity = Expression.Parameter(typeof(TEntity)); 
     var pa = Expression.Invoke(PropertyAccessor, entity); 
     var te = Expression.Invoke(TestExpression, pa); 
     return (Expression<Func<TEntity, bool>>) Expression.Lambda(te, entity); 
    } 
} 

He probado esto y funciona como me esperaba.

Sin embargo, al volver a leer su pregunta original (antes de mis ediciones), estoy empezando a dar la impresión de que hizo una pregunta incorrecta y que probablemente no necesita árboles de expresiones. Si todo lo que necesita es funciones, entonces se puede utilizar sin Expression:

private Func<TEntity, TPropertyResult> PropertyAccessor { get; set; } 
private Func<TPropertyResult, bool> TestExpression { get; set; } 
private Func<TEntity, bool> Combined 
{ 
    get 
    { 
     return entity => TestExpression(PropertyAccessor(entity)); 
    } 
} 

Ejemplo de uso:

// Set up the original functions 
PropertyAccessor = entity => GenerateResult(entity); 
TestExpression = result => result.IsCool(); 

// This stores a reference to the combined function 
var fn = Combined; 

// This actually evaluates the function 
bool isCool = fn(myEntity); 

// Alternatively, you could evaluate the function directly, without the variable 
bool isCool = Combined(myEntity); 
+0

Wow gracias por esta respuesta de trabajo. Me salí la cabeza al sumergirme en la expresión. Supongo que mirar el código ASP.NET MVC te hace pensar que 'Expresión ' es necesaria en todas partes. –

+0

Marc Gravell tiene un excelente artículo sobre InfoQ sobre cómo y por qué debería usar Expression y algunos buenos ejemplos concretos. http://www.infoq.com/articles/expression-compiler –

+0

Gracias, tengo que usarlo en 'linq to sql' pero aparece este error:' LINQ expression node type 'Invoke' no es compatible con LINQ a las entidades. ¿Pueden ayudarme por favor? – Mohsen

Cuestiones relacionadas