2009-08-19 16 views
43

Así que aquí está el escenario: tengo una serie de diferentes clases de repositorio que pueden usar un contexto de datos aislado o un contexto compartido. En los casos en que se utiliza un contexto aislado, quiero agregar un método a la clase base que me permita especificar el lambda como parámetro, hacer que esa expresión sea ejecutada por el contexto aislado del repositorio elegido y devolver un resultado IQueryable . ¿Cómo se vería la firma del método y cómo pasar la expresión al contexto?LINQ: pasando la expresión lambda como parámetro para ser ejecutado y devuelto por el método

Necesito que la solución sea lo más genérica posible ya que podría usarse cualquier objeto/tabla posible.

Aquí es básicamente lo que estoy buscando hacer:

IAssetRepository repo = new AssetRepository(true); // true indicates isolated context 
var results = repo.ExecuteInContext<SomeType>(SomeTable.Where(x => 
               x.SomeProp.Equals(SomeValue))); 

Respuesta

57

Algo como esto:

public IEnumerable<T> ExecuteInContext<T>(
    Expression<Func<T,bool>> predicate) 
{ 
    ... // do your stuff 
    //eg 
    Table<T> t = GetTable<T>(); 
    return t.Where(predicate); 
} 

o

public IEnumerable<T> ExecuteInContext<T>(
    IQueryable<T> src, Expression<Func<T,bool>> predicate) 
{ 
    return src.Where(predicate); 
} 

Uso:

var r = repo.ExecuteInContext<SomeType>( 
      x => x.SomeProp.Equals(Somevalue)); 

o

var r = repo.ExecuteInContext(GetTable<T>(), 
      x => x.SomeProp.Equals(Somevalue)); 

Supuestos:

  1. tabla se puede derivar a partir de T, de lo contrario tendrán que pasar la fuente también.
  2. Ya sabe cómo modificar la expresión del predicado si es necesario.
+0

Cuando se trata de su primera sugerencia, me sale un error en la compilación de la tabla t = GetTable (); línea: T debe ser un tipo de referencia para usarlo como parámetro –

+0

No importa, lo tengo. necesario agregar "donde T: clase" al final de la declaración del método. –

+0

Disculpe, se colgó en el trabajo :) – leppie

6

Salida PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

Este código empaquetar su cláusula where como objetos de expresión que se pueden pasar alrededor.

Implementé el patrón Repositorio, y mi flava es para darle un método Fetch (ICriteria), que construye la cláusula Where dependiendo de los criterios suministrados. Simple, pero funciona para mi

12

Aquí es una muestra completa de trabajo cómo pasar expresión LINQ como parámetro

using System; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace ConsoleTest 
{ 
    public class Values 
    { 
     public int X { get; set; } 
     public int Y { get; set; } 

     public override string ToString() 
     { 
      return String.Format("[ X={0} Y={1} ]", X, Y); 
     } 
    } 

    class Program 
    { 
     static void Main() 
     { 
      var values = new Values {X = 1, Y = 1}; 

      // pass parameter to be incremented as linq expression 
      IncrementValue(values, v => v.X); 
      IncrementValue(values, v => v.X); 
      IncrementValue(values, v => v.Y); 

      // Output is: [ X=3 Y=2 ] 
      Console.Write(values); 
     } 

     private static void IncrementValue<T>(T obj, Expression<Func<T,int>> property) 
     { 
      var memberExpression = (MemberExpression)property.Body; 
      var propertyInfo = (PropertyInfo)memberExpression.Member; 
      // read value with reflection 
      var value = (int)propertyInfo.GetValue(obj, null); 
      // set value with reflection 
      propertyInfo.SetValue(obj, ++value, null); 
     } 
    } 
} 
+0

El enlace en la parte superior de esta respuesta está roto. – Scott

+1

Enlace eliminado. Se proporciona un ejemplo de código con respuesta –

Cuestiones relacionadas