Подтвердить что ты не робот

LINQ: передача лямбда-выражения в качестве параметра для выполнения и возврата методом

Итак, вот сценарий: у меня есть ряд разных классов репозитория, каждый из которых может использовать изолированный контекст данных или общий контекст. В случаях, когда используется изолированный контекст, я хочу добавить метод к базовому классу, который позволит мне указать lambda в качестве параметра, выполнить это выражение изолированным контекстом выбранного репозитория и вернуть результат IQueryable, Как будет выглядеть подпись метода и как передать выражение в контекст?

Мне нужно, чтобы решение было как можно более общим, поскольку можно использовать любой возможный модельный объект/таблицу.

Вот в основном то, что я ищу:

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

Ответ 1

Что-то вроде этого:

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

или

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

Использование:

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

или

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

Предположения:

  • Таблица может быть получена из T, иначе вам также нужно будет передать источник.
  • Вы знаете, как изменить выражение предиката, если это необходимо.

Ответ 2

Вот полный рабочий пример, как передать выражение LINQ в качестве параметра

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

Ответ 3

Проверьте PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

Этот код упакует ваше предложение where как объекты Expression, которые вы можете передать.

Я реализовал шаблон репозитория, и мой flava должен дать ему метод Fetch (ICriteria), который создает предложение Where в зависимости от поставленных критериев. Простой, но работает для меня.