[英]Convert Expression<Func<T, object>> to Expression<Func<object>>
How to convert : Expression<Func<T, object>>
to Expression<Func<object>>
? 如何转换:
Expression<Func<T, object>>
到Expression<Func<object>>
?
For example: 例如:
public class Entity
{
public virtual long Id { get; set; }
}
Origin: 起源:
Expression<Func<Entity, object>> origin = x => x.Id;
Destination: 目的地:
Entity alias = null;
Expression<Func<object>> destination = () => alias.Id;
Actually I'm trying to create a custom cacheable ResultTransformer for Nhibernate. 实际上,我正在尝试为Nhibernate创建一个自定义的可缓存ResultTransformer。 There is a method
public QueryOverProjectionBuilder<T> WithAlias(Expression<Func<object>> alias);
有一个
public QueryOverProjectionBuilder<T> WithAlias(Expression<Func<object>> alias);
But in my classes for each particular entitites I would like to use more specific selector like Expression<Func<T, object>>
但是在我的类中,对于每个特定实体,我想使用更特定的选择器,例如
Expression<Func<T, object>>
You have two options: 您有两种选择:
Option 1 is as simple as Expression.Invoke
but may not be compatible with libraries such as LINQ. 选项1与
Expression.Invoke
一样简单,但可能与LINQ等库不兼容。 Option 2 is best done using an expression visitor: 选项2最好使用表达式访问者来完成:
private class ExchangeParametersVisitor : ExpressionVisitor
{
public ParameterExpression Parameter { get; set; }
public Expression Value { get; set; }
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == Parameter)
{
return Value;
}
return node;
}
}
What you need to do is apply the visitor to the body of your lambda expression and use it to create a new lambda expression that contains all parameters as before except the one you replaced. 您需要做的是将访问者应用于lambda表达式的主体,并使用它来创建一个新的lambda表达式,该表达式包含与之前相同的所有参数,但您替换的参数除外。
That's what Expression.Invoke
is for. 这就是
Expression.Invoke
目的。
Create a new lambda expression, and use Expression.Invoke
on the original expression to compose the two expressions. 创建一个新的lambda表达式,然后对原始表达式使用
Expression.Invoke
组成两个表达式。
Sample: 样品:
Expression<Func<string, int>> inner = x => int.Parse(x);
var outer = Expression.Lambda<Func<int>>
(Expression.Invoke(inner, Expression.Constant("123")));
outer.Compile()().Dump(); // 123
Sadly, some expression parsers don't handle Invoke
correctly - they assume it to be an invocation of a method, and reject it. 遗憾的是,某些表达式解析器无法正确处理
Invoke
他们认为它是方法的调用,并拒绝它。 In that case, you need to inline the expression. 在这种情况下,您需要内联表达式。 That means visiting the whole inner expression and replacing the
ParameterExpression
s with variables in the better case, or if parser doesn't support that either, inlining the argument in all the places. 这意味着访问整个内部表达式,并在更好的情况下用变量替换
ParameterExpression
,或者如果解析器也不支持,则在所有位置插入参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.