我有一个 LambdaExpression,它将一个对象作为参数并最终返回一个对象。出于测试的目的,这里有一个 Lambda(创建以匹配我真正传入的内容),它返回一个作为对象装箱的 DateTime。为了解决这个问题,LambdaExpression 接受一个 XmlNode 并返回一个对象。它必须返回一个对象,真正的返回类型可以是以下任何一种: DateTime,bool,int,decimal,XmlDocument [到目前为止] 一般的想法是在解析器深处的某个地方,这个 lambda 被创建并从中提取一个值输入参数并返回它输入的,但装在一个对象中。
XmlNode node = null;
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicNode), "instance");
ParameterExpression result = Expression.Parameter(typeof(object), "result");
LabelTarget blockReturnLabel = Expression.Label(typeof(object));
BlockExpression block = Expression.Block(
typeof(object),
new[] { result },
Expression.Assign(result, Expression.Convert(Expression.Constant(DateTime.Now.AddSeconds(-1)), typeof(object))),
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))));
LambdaExpression lax = Expression.Lambda<Func<XmlNode, object>>(block, instanceExpression);
稍后在代码中,我们正在评估 <、<=、>、>=、== 和 !=,因此我们希望将此 LambdaExpression 的结果与另一个 Expression 进行比较
通常,我们可以假设 LambdaExpression 位于 Expression.LessThan 右侧的左侧,几乎可以是任何表达式,但假设它是输入的。这意味着它可能是 ConstantExpression 或类似的......但它有一个类型。
这意味着 Expression.LessThan [例如] 失败,因为在调用 Expression.Invoke 时 LambdaExpression 返回一个对象,而 RHS 是该类型的任何类型。
假设从 LambdaExpression 返回的对象内装箱的类型实际上与右侧的类型相当;例如
(object)5 < 6
如何编写一个可以将装箱类型与未装箱类型进行比较而不会崩溃的表达式?我在 linqpad 中尝试了各种排列,包括尝试用普通的 c# 编写它——即没有表达式,只是嵌套了 if-then-else 但是我无法让它完全正确地工作。通常,我可能会写这样的东西:
/*
int i = 3;
object o = (object)i;
int compare = 4;
*/
DateTime dt = DateTime.Now;
object o = (object)dt;
DateTime compare = DateTime.Now.AddSeconds(1);
bool b = false;
if(o.GetType().IsAssignableFrom(compare.GetType()))
{
if(o is int)
{
b = (int)o < (int)(object)compare;
}
if(o is DateTime)
{
b = (DateTime)o < (DateTime)(object)compare;
}
if(o is decimal)
{
b = (decimal)o < (decimal)(object)compare;
}
}
Console.WriteLine(b);
这样,假设 o 和 compare 实际上是相同的类型,并且其中一个被装箱为对象,我们仍然可以执行 < 操作...
所以我想我的问题是,当我在左边有一个 LambdaExpression 和在右边的 Expression 时,我该如何编写上面的代码[如果两者不是同一类型,则结果为 false 比崩溃要好]
希望有人能帮忙,
加雷斯