LINQ: передача лямбда-выражения в качестве параметра для выполнения и возврата методом
Итак, вот сценарий: у меня есть ряд разных классов репозитория, каждый из которых может использовать изолированный контекст данных или общий контекст. В случаях, когда используется изолированный контекст, я хочу добавить метод к базовому классу, который позволит мне указать lambda в качестве параметра, выполнить это выражение изолированным контекстом выбранного репозитория и вернуть результат IQueryable, Как будет выглядеть подпись метода и как передать выражение в контекст?
Мне нужно, чтобы решение было как можно более общим, поскольку можно использовать любой возможный модельный объект/таблицу.
Вот в основном то, что я ищу:
IAssetRepository repo = new AssetRepository(true); // true indicates isolated context
var results = repo.ExecuteInContext<SomeType>(SomeTable.Where(x =>
x.SomeProp.Equals(SomeValue)));
Ответы
Ответ 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 в зависимости от поставленных критериев. Простой, но работает для меня.