创建包含外部变量的LambdaExpression
本文关键字:LambdaExpression 变量 包含外 创建 | 更新日期: 2023-09-27 18:25:44
我想创建类似于的lambda
user => user.Address == address
但不是编译的,我想返回LambdaExpression
如果λ像一样保持恒定
user => user.Age == 50
然后我可以使用这种方法
public static LambdaExpression PropertyEqual(Type tEntityType, string propertyName, object value)
{
// entity => entity.PropName == const
var itemParameter = Expression.Parameter(tEntityType, "entity");
return Expression.Lambda
(
Expression.Equal
(
Expression.Property
(
itemParameter,
propertyName
),
Expression.Constant(value) // Tried to replace this with Expression.Parameter or Expression.Variable but no luck
),
new[] { itemParameter }
);
}
如何使此方法接受来自lambda表达式外部作用域的变量address
?
var addressPropertyName = "Address";
var address = new Address() {...};
var q = Repo.GetQuery().Where(PropertyEqual(typeof(User), addressPropertyName, address))
编辑:澄清我的问题:如何构建正确的Expression
来生成第一个lambda?
更新:这是不可能的,因为EF不支持非标量变量
按照这里的建议,我将lambda更改为user => user.AddressId == addressId
。关键在于如何从已知的导航属性Address
中获得AddressId
FK PropertyInfo
。
您不能在变量上动态生成闭包(您不能在其上下文之外延长变量的生存期),因为这是编译器的一个技巧(重写代码以实现此目的)。
如果您不想要闭包,但想要一个额外的参数,则可以向表达式添加一个额外参数。
你可以
Expression<Func<string>> myExpr = () => address;
现在,您的地址周围有一个表达式。现在你只需要把这两个表达式组合起来。
您必须将方法更改为:
public static LambdaExpression PropertyEqual<T>(Type tEntityType, string propertyName, Expression<Func<T>> getValue)
{
// entity => entity.PropName == const
var itemParameter = Expression.Parameter(tEntityType, "entity");
return Expression.Lambda
(
Expression.Equal
(
Expression.Property
(
itemParameter,
propertyName
),
Expression.Invoke(getValue) // You could directly use getValue.Body instead of Expression.Invoke(getValue)
),
new[] { itemParameter }
);
}