2009-08-19 9 views
43

Voici donc le scénario: j'ai une série de classes de référentiel différentes qui peuvent chacune utiliser un contexte de données isolé, ou un contexte partagé. Dans les cas où un contexte isolé est utilisé, je veux ajouter une méthode à la classe de base qui me permettra de spécifier le lambda comme paramètre, avoir cette expression soit exécutée par le contexte isolé du référentiel choisi et retourner un résultat IQueryable . À quoi ressemblerait la signature de la méthode, et comment passer l'expression au contexte?LINQ: Passer l'expression lambda comme paramètre à exécuter et renvoyer par la méthode

J'ai besoin que la solution soit aussi générique que possible car tout objet/tableau de modèle possible pourrait être utilisé.

Voici essentiellement ce que je cherche à faire:

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

Répondre

57

Quelque chose comme ceci:

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

ou

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

Utilisation:

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

ou

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

Hypothèses:

  1. Table peut être dérivée de T, sinon vous devrez passer aussi la source.
  2. Vous savez comment modifier l'expression de prédicat si nécessaire.
+0

Lorsque vous essayez votre première suggestion, je reçois une erreur dans la compilation du tableau t = GetTable (); line: T doit être un type de référence pour pouvoir l'utiliser comme paramètre –

+0

nevermind, je l'ai. nécessaire d'ajouter "where T: class" à la fin de la déclaration de méthode. –

+0

Désolé, j'ai raccroché au travail :) – leppie

6

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

Ce code empaqueter votre clause where comme des objets d'expression que vous pouvez passer au sujet.

J'ai implémenté le modèle Repository, et mon flava doit lui donner une méthode Fetch (ICriteria), qui construit la clause Where en fonction des critères fournis. Simple, mais fonctionne pour moi.

12

Voici un échantillon de travail complet comment passer l'expression LINQ comme paramètre

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

Le lien en haut de cette réponse est cassé. – Scott

+1

Lien supprimé. L'exemple de code est fourni avec une réponse –

Questions connexes