Так что с точки зрения выражения значение является константой. Это не может быть изменено выражением.
То, что у вас есть, является потенциально открытым замыканием - то есть значение может меняться между выполнениями выражения, но не во время него. Так что это «константа». Это различие между миром функционального программирования и нефункционального программирования :).
Рассмотрим
int a =2;
Expression<Func<int, int>> h = x=> x+ a;
Expression<Func<int, int>> j = x => x +2;
a = 1;
термин a является доступом члена к анонимному классу, который оборачивает и обращается к переменной в стеке. Первый узел - это узел MemberAccess, затем под ним - выражение является константой.
Для кода выше:
((SimpleBinaryExpression)(h.Body)).Right
{value(WindowsFormsApplication6.Form1+<>c__DisplayClass0).a}
CanReduce: false
DebugView: ".Constant<WindowsFormsApplication6.Form1+<>c__DisplayClass0>(WindowsFormsApplication6.Form1+<>c__DisplayClass0).a"
Expression: {value(WindowsFormsApplication6.Form1+<>c__DisplayClass0)}
Member: {Int32 a}
NodeType: MemberAccess
Type: {Name = "Int32" FullName = "System.Int32"}
И константа под ней:
((MemberExpression)((SimpleBinaryExpression)(h.Body)).Right).Expression
{value(WindowsFormsApplication6.Form1+<>c__DisplayClass0)}
CanReduce: false
DebugView: ".Constant<WindowsFormsApplication6.Form1+<>c__DisplayClass0>(WindowsFormsApplication6.Form1+<>c__DisplayClass0)"
NodeType: Constant
Type: {Name = "<>c__DisplayClass0" FullName = "WindowsFormsApplication6.Form1+<>c__DisplayClass0"}
Value: {WindowsFormsApplication6.Form1.}
}
}
Старая добрая 2 выходит на:
((SimpleBinaryExpression)(j.Body)).Right
{2}
CanReduce: false
DebugView: "2"
NodeType: Constant
Type: {Name = "Int32" FullName = "System.Int32"}
Value: 2
Так что я не знаю, помогает ли это вам или нет. Вы можете сказать, посмотрев на родительский узел - или тип объекта, к которому обращается родительский узел.
Добавление в результате вашего уточнения -
поэтому, когда вы говорите
user => user.Email == email
Вы имеете в виду, что ищите всех пользователей с электронной почтой, равной переданному параметру - однако это выражение ссылки означает что-то совсем другое.
что вы хотите сказать, это
Expression<Func<User, string, bool>> (user, email) => user.Email == email
Таким образом, электронная почта теперь будет параметром. Если вам это не нравится, есть еще одна вещь, которую вы можете сделать.
Второй пример будет работать просто отлично - никаких дополнительных параметров не требуется.
t => t.Status != TaskStatus.Done && t.Status != TaskStatus.Failed
Редактировать: добавив еще один способ:
Итак, одна из вещей, которые вы должны были сделать, чтобы ваш код работал, было объявить строковое электронное письмо за пределами лямбды - это немного неуклюже.
Вы могли бы лучше определить параметры, поместив их в определенное место, например, в статический класс. Затем, проходя через лямбду, вам не нужно смотреть на какой-то ужасный объект укрытия - но хороший статический класс вашего творения.
public static class Parameter
{
public static T Input<T>(string name)
{
return default(T);
}
}
Тогда ваш код выглядит так:
Expression<Func<User, bool>> exp = x => x.Email == Parameter.Input<String>("email");
Затем вы можете пройтись по дереву - когда вы приходите к вызову статического класса Parameter, вы можете посмотреть на тип и имя (в коллекции аргументов), и вы начнете ....