转换表达 (Convert Expression> to Expression

2019-07-21 00:03发布

我找不到从表达<Func键<T1,布尔>>转换为表达<Func键<T2,布尔>>的方式。 由于即时通讯使用了很多反思的,其实,我真正需要的是这需要一个类型参数并执行转换的方法。

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]

我想应用到一个列表<T2>

Answer 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);
        }
    }


Answer 2:

你的要求是非常不明智的。 如何将编译器永远不知道如果T1是可以转换为T2? 好像要求即使是可能可怕的运行时错误。*

(*我,因为你正试图恢复体力与嵌套泛型类型组合不认为它可能。)



Answer 3:

它看起来像你想结合2倍的表达- T2T1的转换,比打电话expr给定的结果。

这个问题讨论结合两个表达式(表达式<Func键<T,布尔>>)的总称。 对于你的情况,我认为你需要Expression.Call构建的换算公式,比再次打电话与转换的结果,原始表达式。



文章来源: Convert Expression> to Expression dynamically