用于检查属性是否等于常量的表达式
本文关键字:常量 表达式 于常量 检查 属性 是否 用于 | 更新日期: 2023-09-27 18:34:27
>我正在尝试组合两个工作表达式。
-
left:返回属性值的表达式
Expression<Func<TimeSlot, Guid>> left = x => x.TimeSlotId;
-
right:返回常量值(变量
guid
的值)的表达式Expression<Func<TimeSlot, Guid>> right = Expression.Lambda<Func<TimeSlot, Guid>> (Expression.Constant(guid, typeof(Guid)), input);
现在,我想将这两个表达式打包到另一个表达式中,以等同于这两个结果。这有效:
// given a TimeSlot slot which guid is equal to the constent
bool eq1 = left.Compile()(slot) == right.Compile()(slot); // true
但这行不通 ParameterExpression input = Expression.Parameter(typeof(TimeSlot));
Expression<Func<TimeSlot, bool>> expression = Expression.Lambda<Func<TimeSlot, bool>>
(Expression.Equal(left, right), input);
bool eq2 = expression.Compile()(slot); // false
我完全困惑为什么这个结果是不同的。特别是因为这个表达式的调试视图看起来像这样:
{Param_0 => (x => x.TimeSlotId == Param_0 => 351155b2-20a5-4c48-8722-ddf0e1f9055a)}
=
.Lambda #Lambda1<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Boolean]>(SilverFit.Database.Model.TimeSlot $var1)
{
.Lambda #Lambda2<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]> == .Lambda #Lambda3<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]>
}
.Lambda #Lambda2<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]>(SilverFit.Database.Model.TimeSlot $x) {
$x.TimeSlotId
}
.Lambda #Lambda3<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]>(SilverFit.Database.Model.TimeSlot $var1) {
.Constant<System.Guid>(351155b2-20a5-4c48-8722-ddf0e1f9055a)
}
有谁知道创建比较表达式和常量结果的表达式的正确方法?
您看到的调试输出准确地告诉您发生了什么,以及它不起作用的原因。特别是,您与相等表达式进行比较的内容不是表达式返回的值,而是表达式本身。
一个重要的线索是两个表达式都需要输入,但即使在调试输出中,您也可以看到该输入仅在相等比较的一侧使用,并且仅作为第二个表达式的输入参数。
实际上,恕我直言,分别编译这两个表达式并不是一个糟糕的解决方案。您甚至可以缓存编译结果:
Func<TimeSlot, Guid> d1 = left.Compile(), d2 = right.Compile();
Func<TimeSlot, bool> d2 = x => d1(x) == d2(x);
但是,如果您真的想将操作组合为单个表达式,那么您可以这样做:
ParameterExpression param1 = Expression.Parameter(typeof(TimeSlot));
Expression<Func<TimeSlot, bool>> expression = Expression.Lambda<Func<TimeSlot, bool>>(
Expression.Equal(
Expression.Invoke(left, param1),
Expression.Invoke(right, param1)),
param1);
下面是演示该技术的完整代码示例:
class Program
{
class A
{
public Guid Guid { get; private set; }
public A()
{
Guid = Guid.NewGuid();
}
}
static void Main(string[] args)
{
// Set up data values
A a = new A();
Guid guid = a.Guid;
// Create expressions to be composed
Expression<Func<A, Guid>> e1 = arg => arg.Guid, e2 = arg => guid;
// Create lambda expression: invoke both expressions, compare the result
ParameterExpression param1 = Expression.Parameter(typeof(A));
Expression<Func<A, bool>> e3 = Expression.Lambda<Func<A, bool>>(
Expression.Equal(
Expression.Invoke(e1, param1),
Expression.Invoke(e2, param1)),
param1);
// Compile to an actual delegate instance
Func<A, bool> d1 = e3.Compile();
// Check the result
Console.WriteLine(d1(a));
}
}