2009-08-19 6 views
43

Quindi, ecco lo scenario: ho una serie di classi di repository diverse che ognuna può utilizzare un contesto di dati isolato o un contesto condiviso. Nei casi in cui viene utilizzato un contesto isolato, voglio aggiungere un metodo alla classe base che mi consenta di specificare il lambda come parametro, fare in modo che quell'espressione sia eseguita dal contesto isolato del repository scelto e restituire un risultato IQueryable . Come apparirebbe la firma del metodo e come passare l'espressione al contesto?LINQ: passaggio dell'espressione lambda come parametro da eseguire e restituito con il metodo

Ho bisogno che la soluzione sia il più generica possibile di qualsiasi oggetto/tabella modello possibile.

Qui è fondamentalmente quello che sto cercando di fare:

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

risposta

57

Qualcosa di simile a questo:

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); 
} 

Usage:

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

o

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

Ipotesi:

  1. tabella può essere derivati ​​da T, altrimenti sarà necessario passare alla sorgente troppo.
  2. Sapete come modificare l'espressione del predicato se necessario.
+0

Quando si cerca il tuo primo suggerimento, ottengo un errore nella compilazione della tabella t = GetTable (); linea: T deve essere un tipo di riferimento per poterlo utilizzare come parametro –

+0

, ho capito. necessario aggiungere "where T: class" alla fine della dichiarazione del metodo. –

+0

Scusa, sono stato bloccato al lavoro :) – leppie

6

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

Questo codice confezionare il vostro clausola WHERE come oggetti di espressione che è possibile passare circa.

Ho implementato il modello di repository e il mio flava consiste nel dargli un metodo Fetch (ICriteria), che crea la clausola Where in base ai criteri forniti. Semplice, ma funziona per me.

12

Ecco un esempio di lavoro completo come passare l'espressione LINQ come parametro

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

Il collegamento nella parte superiore di questa risposta è rotto. – Scott

+1

Link rimosso. L'esempio di codice è fornito con la risposta –

Problemi correlati