2009-03-24 21 views
7

tengo método de extensión:Cambio de parámetros de función lambda de expresión lambda

public static IQueryable<TResult> WithFieldLike<TResult>(
    this IQueryable<TResult> query, 
    Func<TResult, string> field, 
    string value) 
{ 
    Expression<Func<TResult, bool>> expr = 
     trans => field(trans).Contains(value); 
    return query.Where(expr); 
} 

necesito campo de parámetro de cambio para escribir: Expresión>. Será algo así como

public static IQueryable<TResult> WithFieldLike<TResult>(
    this IQueryable<TResult> query, 
    Expression<Func<TResult, string>> field, 
    string value) 
{ 
    Expression<Func<TResult, bool>> expr = ??? 
    return query.Where(expr); 
} 

La llamada de este método es:

var query7 = query.WithFieldLike(trans => trans.DeviceModelNumber, "ber_3"); 

¿Cómo debo construir el "expr" en este caso? Por favor ayuda.

+0

Añada el lenguaje de las etiquetas. – Svante

Respuesta

6

Deconstruct field y crear una nueva expresión, algo como esto:

var expr = Expression.Lambda<Func<TResult, bool>> (
    Expression.Call (field.Body, typeof (string).GetMethod ("Contains"), 
     Expression.Constant (value)), field.Parameters) ; 

(editada como por el refinamiento de Maxs en comentarios)

+0

El punto es que no puedo construir la expresión "Contiene". Cómo construir la expresión "Igual". Lo sé. – Maxs

+0

Vaya, lo siento - respuesta editada –

+0

Gracias. Esto funciona perfectamente – Maxs

1

Uso Compile para obtener la lambda de vuelta:

Expression<Func<TResult, bool>> expr = 
    trans => field.Compile()(trans).Contains(value); 

Editar: ¡Vaya - mi compilador de aire me falló. Después de compilar, obtienes el delegado. Pero aún necesita llamar para obtener la cadena para llamar a Contiene.

+0

Será un error de compilación: 'System.Func ' no contiene una definición para 'Contiene' y ningún método de extensión 'Contiene' que acepte un primer argumento de tipo 'System.Func ' podría ser encontrado (¿echas en falta una directiva de uso o una referencia de ensamblado?) – Maxs

+0

@Maxs: Sí, arruiné toda la parte de "convertirlo en otra expresión". Sin embargo, Point se apoya en el uso de Compile para obtener el lambda y lo usa normalmente. –

4

Tendrá que utilizar Expression.Invoke; algo así (no probado):

public static IQueryable<TResult> WithFieldLike<TResult>(
    this IQueryable<TResult> query, 
    Expression<Func<TResult, string>> field, 
    string value) 
{ 
    var param = Expression.Parameter(typeof(TResult), "x"); 
    var expr = Expression.Lambda<Func<TResult, bool>>(
     Expression.Call(Expression.Invoke(field, param), 
      "Contains", null, Expression.Constant(value)), param); 

    return query.Where(expr); 
} 

(edit: fija)

+1

Gracias. Esto también funciona Pero genera una expresión incompatible con la llamada a ADO.NET Data Services. – Maxs

+1

Tengo que amar la Ley de las Extracciones Leaky ... funciona con algunas pero no con todas ;-p –