C# 在LinQ表达式树中声明变量
在前面的问题()中,我通过使用C# 在LinQ表达式树中声明变量,c#,.net,linq,lambda,expression,C#,.net,Linq,Lambda,Expression,在前面的问题()中,我通过使用let语句声明变量来解决问题,我的代码如下所示: return from q in pList let currentContract = q.StaffContracts.OrderByDescending(p => p.SignedDate).Where(p => p.Active).FirstOrDefault() where (currentContract.Timespan >= fromValue && currentC
let
语句声明变量来解决问题,我的代码如下所示:
return
from q in pList
let currentContract = q.StaffContracts.OrderByDescending(p => p.SignedDate).Where(p => p.Active).FirstOrDefault()
where (currentContract.Timespan >= fromValue && currentContract.Timespan <= toValue)
select q;
编译错误消息为:
具有语句体的lambda表达式无法转换为表达式树
有什么解决方法吗?恐怕您必须使用
System.Linq.Expressions.expression
类方法手动准备表达式:
public static Expression<Func<Item, bool>> GetWhere(TimeSpan fromValue, TimeSpan toValue)
{
Expression<Func<Item, Contract>> currentContract =
q => q.StaffContracts
.OrderByDescending(p => p.SignedDate)
.Where(p => p.Active)
.FirstOrDefault();
var param = currentContract.Parameters.First();
return Expression.Lambda<Func<Item, bool>>(
Expression.And(
Expression.And(
Expression.NotEqual(
currentContract,
Expression.Constant(null, typeof(Contract))),
Expression.GreaterThanOrEqual(
Expression.Property(currentContract, "Timespan"),
Expression.Constant(fromValue))),
Expression.LessThanOrEqual(
Expression.Property(currentContract, "Timespan"),
Expression.Constant(toValue))),
param);
}
公共静态表达式GetWhere(TimeSpan-fromValue,TimeSpan-toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
var param=currentContract.Parameters.First();
返回表达式.Lambda(
表达。及(
表达。及(
表达式。NotEqual(
当前合同,
表达式.Constant(null,typeof(Contract)),
表达式。大于或等于(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(fromValue)),
Expression.LessThanOrEqual(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(toValue)),
参数);
}
恐怕您必须使用System.Linq.Expressions.expression
类方法手动准备表达式:
public static Expression<Func<Item, bool>> GetWhere(TimeSpan fromValue, TimeSpan toValue)
{
Expression<Func<Item, Contract>> currentContract =
q => q.StaffContracts
.OrderByDescending(p => p.SignedDate)
.Where(p => p.Active)
.FirstOrDefault();
var param = currentContract.Parameters.First();
return Expression.Lambda<Func<Item, bool>>(
Expression.And(
Expression.And(
Expression.NotEqual(
currentContract,
Expression.Constant(null, typeof(Contract))),
Expression.GreaterThanOrEqual(
Expression.Property(currentContract, "Timespan"),
Expression.Constant(fromValue))),
Expression.LessThanOrEqual(
Expression.Property(currentContract, "Timespan"),
Expression.Constant(toValue))),
param);
}
公共静态表达式GetWhere(TimeSpan-fromValue,TimeSpan-toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
var param=currentContract.Parameters.First();
返回表达式.Lambda(
表达。及(
表达。及(
表达式。NotEqual(
当前合同,
表达式.Constant(null,typeof(Contract)),
表达式。大于或等于(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(fromValue)),
Expression.LessThanOrEqual(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(toValue)),
参数);
}
因此,我们可以在这里创建一个Compose
方法,该方法采用一个表达式
,表示一个具有一个参数和一个返回值的lambda,然后采用第一个lambda的输出作为输入的第二个lambda,然后返回一个新的lambda,该lambda接受第一个参数的输入并返回第二个参数的输出
如果它只是常规委托,那么该方法看起来会像这样(只是为了让您了解它在概念上的作用):
这使用以下方法将一个表达式的所有实例替换为另一个:
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
现在我们有了Compose
方法,我们可以编写一个表达式,它接受您的一项并返回一个契约
,然后编写另一个方法,接受该契约并计算一个bool
,指示它是否有效:
public static Expression<Func<Item, bool>> GetFilter(
TimeSpan fromValue, TimeSpan toValue)
{
Expression<Func<Item, Contract>> currentContract =
q => q.StaffContracts
.OrderByDescending(p => p.SignedDate)
.Where(p => p.Active)
.FirstOrDefault();
return currentContract.Compose(contract =>
contract != null &&
contract.TimeSpan >= fromValue &&
contract.TimeSpan <= toValue);
}
公共静态表达式GetFilter(
TimeSpan fromValue,TimeSpan toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
返回currentContract.Compose(合同=>
合同!=null&&
contract.TimeSpan>=fromValue&&
contract.TimeSpan因此,我们可以在这里创建一个Compose
方法,该方法使用一个表达式
表示一个lambda,其中包含一个参数和一个返回值,然后使用第一个lambda的输出作为输入,然后返回一个新的lambda,该lambda接受第一个参数的输入并返回second参数的输出
如果它只是常规委托,那么该方法看起来会像这样(只是为了让您了解它在概念上的作用):
这使用以下方法将一个表达式的所有实例替换为另一个:
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
现在我们有了Compose
方法,我们可以编写一个表达式,它接受您的一项并返回一个契约
,然后编写另一个方法,接受该契约并计算一个bool
,指示它是否有效:
public static Expression<Func<Item, bool>> GetFilter(
TimeSpan fromValue, TimeSpan toValue)
{
Expression<Func<Item, Contract>> currentContract =
q => q.StaffContracts
.OrderByDescending(p => p.SignedDate)
.Where(p => p.Active)
.FirstOrDefault();
return currentContract.Compose(contract =>
contract != null &&
contract.TimeSpan >= fromValue &&
contract.TimeSpan <= toValue);
}
公共静态表达式GetFilter(
TimeSpan fromValue,TimeSpan toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
返回currentContract.Compose(合同=>
合同!=null&&
contract.TimeSpan>=fromValue&&
contract.TimeSpan尝试从此[此处链接][1][1]获取更多信息:尝试从此[此处链接][1][1]获取更多信息:您正在对currentContract
执行操作,就好像它是一个Contract
对象一样,但它不是。它是一个表示获取函数的表达式,因此您的代码无法工作。也许您是想获取该表达式的主体?我没有测试它,但我希望它与return q=>q.StaffContracts.orderByDescent相同ing(p=>p.SignedDate).Where(p=>p.Active).FirstOrDefault()!=null&&q.StaffContracts.OrderByDescending(p=>p.SignedDate).Where(p=>p.Active).FirstOrDefault().Timespan>fromValue&&q.StaffContracts.OrderByDescending(p=>p.SignedDate).Where(p=>p.Active).FirstOrDefault().Timespan
,这就是我希望它能工作的原因。但它不会成功