如果我手动构建表达式树,运行时似乎会自动确定返回类型。所以,如果我构建一个如下所示的表达式树:
// Order contains a navigation property for Customer
(Order o) => o.Customer;
运行时将返回类型确定为Customer,基本上是:
Expression<Func<Order, Customer>> efd = (Order o) => o.Customer;
我如何构建它 - 或者改变我构建的内容,所以返回是对象,即表达式为:
Expression<Func<Order, object>> ef = (Order o) => o.Customer;
这是通用的,我不知道在编译时返回类型是Customer;它可以是(在这种情况下)订单中的任何导航。
澄清
让我说我从这样的表达开始:
Expression<Func<OrderDTO, object>> ef = (OrderDTO o) => o.Customer;
我有一个正在重建此例程的例程,通过遍历树并根据from / to类型的地图更改类型,将OrderDTO
的类型更改为Order
。这就是我正在做的,但结果表达式是
Expression<Func<Order, Customer>> ef = (Order o) => o.Customer;
因此,当我重建树时,我需要以某种方式指定返回类型 - 它看起来好像系统正在自动确定返回类型,因为我还没有指定它。谢谢,Ray
答案 0 :(得分:1)
如果没有实际看到您的代码,很难说,但看起来您正在使用Expression.Lambda()
版本,而这些版本不允许您指定所创建表达式的类型。如果你这样做,你就会自动决定委托类型。
要解决此问题,您需要使用Expression.Lambda()
版本,该版本允许您使用类型参数(例如Expression.Lambda<Func<Order, object>>(…)
)指定委托类型,或者在您的情况下更可能使用版本其中委托类型被指定为Type
类型的常规参数(Expression.Lambda(funcType, …)
)。
答案 1 :(得分:0)
public class ReturnTypeVisitor<TSource, TReturnValue> : ExpressionVisitor{
protected override Expression VisitLambda<T>(Expression<T> node)
{
var delegateType = typeof(Func<,>).MakeGenericType(typeof(TSource), typeof(TReturnValue));
return Expression.Lambda(delegateType, Visit(node.Body), node.Parameters);
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Member.DeclaringType == typeof(TSource))
{
return Expression.Property(Visit(node.Expression), node.Member.Name);
}
return base.VisitMember(node);
}
}
用法:
public class Foo{
public Bar Bar { get; set; }
}
public class Bar { }
Expression<Func<Foo, object>> expression = p => p.Bar;
Expression<Func<Foo, Bar>> stronglyTypedReturnValue =(Expression<Func<Foo, Bar>>) new ReturnTypeVisitor<Foo, Bar>().Visit(expression);