如何指定表达式树的返回类型?

时间:2013-01-11 23:26:09

标签: c# lambda expression-trees

如果我手动构建表达式树,运行时似乎会自动确定返回类型。所以,如果我构建一个如下所示的表达式树:

// 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

2 个答案:

答案 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);