Convert Expression<Func<T1,bool>> to Expression<Func<T2,bool> dynamically

假如想象 提交于 2019-12-30 02:20:07

问题


I cannot find the way to convert from Expression<Func<T1,bool>> to Expression<Func<T2,bool>>. Since Im using a lot of reflection, in fact, what I really need is a method which takes a type parameter and performs the conversion.

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

T2 is derived from T1

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

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

I am defining a filter expression on the base class

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

that i want to apply to a List<T2>


回答1:


Is this what you're looking for? There are two flavors of the method: the first lets you pass in the new input type as an argument; the second lets you pass in the input type as a generic parameter and get a strongly typed 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);
        }
    }



回答2:


What your asking for is very unwise. How would the compiler ever know if T1 is can be converted to T2? Seems like asking for awful run-time errors even if it is possible.*

(*I don't think its possible since you are trying to combine refection with nested generic types.)




回答3:


It looks like you want to combine 2 expressions - T2 to T1 conversion and than call to expr with given result.

This question discusses Combining two expressions (Expression<Func<T, bool>>) in general. For your case I think you need Expression.Call to construct conversion expression and than again to call original expression with result of conversion.



来源:https://stackoverflow.com/questions/15212779/convert-expressionfunct1-bool-to-expressionfunct2-bool-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!