【问题标题】:Expression<Func<in T, bool>> or Expression<Func<TBase,bool>> to Expression<Func<T,bool>> ConverterExpression<Func<in T, bool>> 或 Expression<Func<TBase,bool>> 到 Expression<Func<T,bool>> 转换器
【发布时间】:2011-05-30 13:53:44
【问题描述】:

有什么简单的转换方法

Expression<Func<TBase,bool>> 

Expression<Func<T,bool>>

T 是从 TBase 继承的?

【问题讨论】:

    标签: c# generics expression-trees


    【解决方案1】:

    只要 T 派生自 TBase,您就可以使用原始表达式的主体和参数直接创建所需类型的表达式。

    Expression<Func<object, bool>> x = o => o != null;
    Expression<Func<string, bool>> y = Expression.Lambda<Func<string, bool>>(x.Body, x.Parameters);
    

    【讨论】:

      【解决方案2】:

      您可能需要手动转换。这样做的原因是您正在有效地转换为它可能的子集。所有T 都是TBase,但并非所有TBase 都是T

      好消息是您可能可以使用Expression.Invoke 来完成此操作,并手动将适当的转换/转换应用到TBase(当然会发现任何类型安全问题)。

      编辑:对于误解您想要进入的方向,我深表歉意。我认为简单地转换表达式仍然是您最好的方法。它使您能够随心所欲地处理转换。 Marc Gravell's answer here 是我见过的最简洁明了的方式。

      【讨论】:

      • 为什么要手动?我将 E 转换为 E>,所以在我使用 TBase 的每个地方我都可以使用 T.
      • 那是我的错。我误解了你想要转换的方向。我的原始答案已更新,提供了一个比我想出的更好答案的链接。
      【解决方案3】:

      为了做到这一点,我编写了 ExpressionVisitor 并重载了 VisitLambda 和 VisitParameter

      这里是:

      public class ConverterExpressionVisitor<TDest> : ExpressionVisitor
      {
          protected override Expression VisitLambda<T>(Expression<T> node)
          {
              var readOnlyCollection = node.Parameters.Select(a => Expression.Parameter(typeof(TDest), a.Name));
              return Expression.Lambda(node.Body, node.Name, readOnlyCollection);
          }
      
          protected override Expression VisitParameter(ParameterExpression node)
          {
              return Expression.Parameter(typeof(TDest), node.Name);
          }
      }
      
      public class A { public string S { get; set; } }
      public class B : A { }
      
      static void Main(string[] args)
      {
          Expression<Func<A, bool>> ExpForA = a => a.S.StartsWith("Foo");
          Console.WriteLine(ExpForA); // a => a.S.StartsWith("Foo");
      
          var converter = new ConverterExpressionVisitor<B>();
          Expression<Func<B, bool>> ExpForB = (Expression<Func<B, bool>>)converter.Visit(ExpForA);
          Console.WriteLine(ExpForB); // a => a.S.StartsWith("Foo"); - same as for A but for B
          Console.ReadLine();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-17
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多