Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ: Passing lambda expression as parameter to be executed and returned by method

Tags:

c#

linq

So here is the scenario: i have a series of different repository classes that each can use an isolated data context, or a shared context. In the cases where an isolated context is being used i want to add a method to the base class that will allow me to specify the lambda as the parameter, have that expression be executed by the isolated context of the chosen repository and return an IQueryable result. How would the method signature look, and how to a pass the expression to the context?

I need the solution to be as generic as possible as any possible model object/table could be used.

Here is basically what i am looking to do:

IAssetRepository repo = new AssetRepository(true); // true indicates isolated context
var results = repo.ExecuteInContext<SomeType>(SomeTable.Where(x => 
                                              x.SomeProp.Equals(SomeValue)));
like image 674
Jason Miesionczek Avatar asked Aug 19 '09 12:08

Jason Miesionczek


People also ask

How do you pass a lambda expression as a parameter in C#?

Using delegates you can pass a lambda expression as a parameter to a function, and then use it in LINQ queries. This can be done with Func<…> delegates. If you want to pass a lambda expression to be used, for example, in Where clause, you need a Func<T, bool> delegate.

What does => mean in LINQ?

The => operator can be used in two ways in C#: As the lambda operator in a lambda expression, it separates the input variables from the lambda body. In an expression body definition, it separates a member name from the member implementation.

What is lambda expression in LINQ C#?

Advertisements. The term 'Lambda expression' has derived its name from 'lambda' calculus which in turn is a mathematical notation applied for defining functions. Lambda expressions as a LINQ equation's executable part translate logic in a way at run time so it can pass on to the data source conveniently.

Can you use lambda expression instead of LINQ query?

So performance-wise, there's no difference whatsoever between the two. Which one you should use is mostly personal preference, many people prefer lambda expressions because they're shorter and more concise, but personally I prefer the query syntax having worked extensively with SQL.


2 Answers

Something like this:

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

or

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

or

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

Assumptions:

  1. Table can be derived from T, else you will need to pass the source too.
  2. You know how to modify the predicate expression if needed.
like image 182
leppie Avatar answered Oct 18 '22 09:10

leppie


Here is a complete working sample how to pass LINQ expression as a parameter

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);
        }
    }
}
like image 45
Maksym Kozlenko Avatar answered Oct 18 '22 09:10

Maksym Kozlenko