【问题标题】:Convert Expression<Func<T1,bool>> to Expression<Func<T2,bool> dynamically将 Expression<Func<T1,bool>> 动态转换为 Expression<Func<T2,bool>
【发布时间】:2013-03-04 22:58:08
【问题描述】:

我找不到从 Expression> 转换为 Expression> 的方法。由于我使用了很多反射,实际上我真正需要的是一个接受类型参数并执行转换的方法。

public object Convert(Expression<Func<T1,bool>> expr, Type t);

T2 源​​自 T1

public class T1 {
     int FamilyId {get; set;}
}

public class T2 : T1 {
     ... other properties
}

我在基类上定义一个过滤器表达式

Expression<Func<T1,bool>> filter = p => p.FamilyId == [some value]

我想申请一个列表

【问题讨论】:

  • what I really need is a method which takes a type parameter and performs the conversion. - 什么? bool 是干什么用的?你需要一个转换方法吗?还是有条件的?我不明白
  • T1T2 有什么关系?有没有办法在它们之间进行转换?
  • T2 派生自 T1。

标签: c# linq reflection lambda


【解决方案1】:

这就是你要找的吗?该方法有两种风格:第一种允许您将新的输入类型作为参数传递;第二个允许您将输入类型作为泛型参数传入并获得强类型的 LambdaExpression。

    public static LambdaExpression ChangeInputType<T, TResult>(Expression<Func<T, TResult>> expression, Type newInputType)
    {
        if (!typeof(T).IsAssignableFrom(newInputType))
            throw new Exception(string.Format("{0} is not assignable from {1}.", typeof(T), newInputType));
        var beforeParameter = expression.Parameters.Single();
        var afterParameter = Expression.Parameter(newInputType, beforeParameter.Name);
        var visitor = new SubstitutionExpressionVisitor(beforeParameter, afterParameter);
        return Expression.Lambda(visitor.Visit(expression.Body), afterParameter);
    }

    public static Expression<Func<T2, TResult>> ChangeInputType<T1, T2, TResult>(Expression<Func<T1, TResult>> expression)
    {
        if (!typeof(T1).IsAssignableFrom(typeof(T2)))
            throw new Exception(string.Format("{0} is not assignable from {1}.", typeof(T1), typeof(T2)));
        var beforeParameter = expression.Parameters.Single();
        var afterParameter = Expression.Parameter(typeof(T2), beforeParameter.Name);
        var visitor = new SubstitutionExpressionVisitor(beforeParameter, afterParameter);
        return Expression.Lambda<Func<T2, TResult>>(visitor.Visit(expression.Body), afterParameter);
    }

    public class SubstitutionExpressionVisitor : ExpressionVisitor
    {
        private Expression before, after;
        public SubstitutionExpressionVisitor(Expression before, Expression after)
        {
            this.before = before;
            this.after = after;
        }
        public override Expression Visit(Expression node)
        {
            return node == before ? after : base.Visit(node);
        }
    }

【讨论】:

  • 当T2不继承自T1时,是否可以做类似的表达?
【解决方案2】:

你的要求是非常不明智的。编译器如何知道 T1 是否可以转换为 T2?似乎要求可怕的运行时错误,即使它是可能的。*

(*我认为这是不可能的,因为您正在尝试将反射与嵌套的泛型类型结合起来。)

【讨论】:

    【解决方案3】:

    您似乎想要组合 2 个表达式 - T2T1 的转换,而不是调用 expr 给定的结果。

    这个问题一般讨论Combining two expressions (Expression<Func<T, bool>>)。对于您的情况,我认为您需要 Expression.Call 来构造转换表达式,而不是再次使用转换结果调用原始表达式。

    【讨论】:

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