60 Stimmen

LINQ: Übergabe eines Lambda-Ausdrucks als Parameter zur Ausführung und Rückgabe durch eine Methode

Hier ist also das Szenario: Ich habe eine Reihe von verschiedenen Repository-Klassen, die jeweils einen isolierten Datenkontext oder einen gemeinsamen Kontext verwenden können. In den Fällen, in denen ein isolierter Kontext verwendet wird, möchte ich der Basisklasse eine Methode hinzufügen, die es mir ermöglicht, das Lambda als Parameter anzugeben, diesen Ausdruck durch den isolierten Kontext des gewählten Repositorys ausführen zu lassen und ein IQueryable-Ergebnis zurückzugeben. Wie würde die Methodensignatur aussehen, und wie kann ich den Ausdruck an den Kontext übergeben?

Die Lösung muss so allgemein wie möglich sein, da alle möglichen Modellobjekte/Tabellen verwendet werden können.

Hier ist im Grunde, was ich zu tun suchen:

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

80voto

leppie Punkte 111830

Etwa so:

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

Verwendung:

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

o

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

Annahmen:

  1. Tabelle kann von T abgeleitet werden, andernfalls müssen Sie auch die Quelle übergeben.
  2. Sie wissen, wie Sie den Prädikatsausdruck bei Bedarf ändern können.

12voto

Maksym Kozlenko Punkte 9891

Hier ist ein vollständiges Arbeitsbeispiel, wie man einen LINQ-Ausdruck als Parameter übergibt

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

6voto

Duncan Punkte 10010

Prüfen Sie den PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

Dieser Code verpackt Ihre Where-Klausel als Expression-Objekte, die Sie weitergeben können.

Ich habe das Repository-Muster implementiert, und mein Flava ist es, eine Fetch(ICriteria)-Methode, die die Where-Klausel in Abhängigkeit von den angegebenen Kriterien aufbaut, zu geben. Einfach, aber funktioniert für mich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X