Я пытаюсь написать статическую функцию для двух выражений, но получаю следующую ошибку:
The parameter 'item' is not in scope.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The parameter 'item' is not in scope.
метод:
public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
// Define the parameter to use
var param = Expression.Parameter(typeof(T), "item");
var filterExpression = Expression.Lambda<Func<T, bool>>
(Expression.Or(
left.Body,
right.Body
), param);
// Build the expression and return it
return (filterExpression);
}
редактировать: добавление дополнительной информации
Выражения, являющиеся или были получены из метода ниже, который выполняется нормально. Если есть лучший способ или результаты, я все уши. Кроме того, я заранее не знаю, сколько их будет.
public static Expression<Func<T, bool>> FilterExpression(string filterBy, object Value, FilterBinaryExpression binaryExpression)
{
// Define the parameter to use
var param = Expression.Parameter(typeof(T), "item");
// Filter expression on the value
switch (binaryExpression)
{
case FilterBinaryExpression.Equal:
{
// Build an expression for "Is the parameter equal to the value" by employing reflection
var filterExpression = Expression.Lambda<Func<T, bool>>
(Expression.Equal(
Expression.Convert(Expression.Property(param, filterBy), typeof(TVal)),
Expression.Constant(Value)
),
param);
// Build the expression and return it
return (filterExpression);
}
редактировать: добавление дополнительной информации
В качестве альтернативы, есть ли лучший способ сделать или? В настоящее время .Where (ограничение) отлично работает там, где ограничение имеет тип Expression>. Как я могу сделать where (constraint1 или constraint2) (к ограничению n'th)
Заранее спасибо!





Проблема в том, что выражение, которое вы создаете в методе OrExpressions, повторно использует тело двух выражений. Эти тела будут содержать ссылки на их собственное ParameterExpression, которое было определено в FilterExpression.
Исправление - переписать левую и правую части, чтобы использовать новое выражение ParameterExpression. Или передать исходное ParameterExpression. Это не потому, что два ParameterExpression имеют одинаковое имя, они представляют один и тот же параметр.
Ты мой друг, потрясающий :)
Я не уверен в правильных терминах здесь, но в основном параметры выражения не эквивалентны, даже если у них одинаковое имя.
Это означает, что
var param1 = Expression.Parameter(typeof(T), "item");
var param2 = Expression.Parameter(typeof(T), "item");
param1 != param2
param1 и param2 не будут одинаковыми, если они используются в выражении.
Лучший способ справиться с этим - заранее создать один параметр для вашего выражения, а затем передать его всем вспомогательным функциям, которым этот параметр нужен.
Обновлено: Кроме того, если вы пытаетесь динамически составлять предложения where в LINQ, вы можете попробовать PredicateBuilder.
Спасибо :) Я переработал метод, чтобы передать тот же параметр в методы помощника, и все снова в порядке. Я смотрю в PredicateBuilder, чтобы, надеюсь, навести порядок.
Будьте осторожны, поскольку PredicateBuilder от Ben & Joe Albahari не работает для Entity Framework. Смотрите мой ответ о фиксированной версии.
Как уже было предложено, здесь вы можете найти этот очень хороший (рабочий) код
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.Or(expr1.Body, invokedExpr), expr1.Parameters);
}
что вы можете адаптироваться к своим потребностям и не привязаны (IMHO) к LINQ.
Будьте осторожны, поскольку этот код не работает для Entity Framework. Смотрите мой ответ о фиксированной версии.
Решение Фабрицио тоже пришло мне в голову, но поскольку я пытался объединить два выражения, которые будут выполняться как sql-запрос linq 2, я думал, что оно будет выполняться в памяти, а не на sql-сервере.
Мне писали - Linq-To-Sql распознает, что вызов является лямбда-выражением, и, таким образом, по-прежнему создает оптимизированный sql.
Тем, кто нашел эту страницу поисковой системой и собирается использовать PredicateBuilder от Бена и Джо Альбахари, будьте осторожны, так как это не работает с Entity Framework.
Вместо этого попробуйте эта фиксированная версия.
Спасибо! Собираюсь попробовать передать тот же параметр сейчас