【问题标题】:How to specify return type of expression tree?如何指定表达式树的返回类型?
【发布时间】:2013-01-11 23:26:08
【问题描述】:

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

// Order contains a navigation property for Customer
(Order o) => o.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;

我有一个例程正在重建它,通过遍历树并根据从/到类型的映射更改类型,将 OrderDTO 的类型更改为 Order。这就是我正在做的所有事情,但结果表达式是

Expression<Func<Order, Customer>> ef = (Order o) => o.Customer;

因此,当我重建树时,我需要以某种方式指定返回类型 - 看起来系统会自动确定返回类型,因为我并没有指定它。谢谢,雷

【问题讨论】:

  • 那么,你最后的表达有什么问题?
  • 这里不完全清楚你在问什么,你是在问如何更改现有表达式树的返回类型?或者您是否在问如何格式化您的 lambda 表达式以便您可以控制返回类型?
  • (Order o) =&gt; (object)o.Customer?
  • 你有没有尝试过类似Func&lt;Order, T&gt; GetLamba&lt;T&gt;(...); 的泛型
  • 你能编辑你的问题并添加你的重写代码吗?

标签: c# lambda expression-trees


【解决方案1】:

如果没有实际看到您的代码,很难说,但看起来您正在使用Expression.Lambda() 的一个版本,它们不允许您指定创建的表达式的类型。如果你这样做,你是对的,委托类型将自动决定。

要解决此问题,您需要使用Expression.Lambda() 的版本,该版本允许您使用类型参数(例如Expression.Lambda&lt;Func&lt;Order, object&gt;&gt;(…))指定委托类型,或者在您的情况下更可能是委托类型所在的版本被指定为Type (Expression.Lambda(funcType, …)) 类型的普通参数。

【讨论】:

    【解决方案2】:
    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-14
      • 2021-01-18
      • 2012-09-01
      • 2014-08-06
      • 1970-01-01
      相关资源
      最近更新 更多