【问题标题】:Convert Expression<Func<T, TProperty>> to Expression<Func<object, object>> and vice versa将 Expression<Func<T, TProperty>> 转换为 Expression<Func<object, object>> 反之亦然
【发布时间】:2014-10-08 09:19:33
【问题描述】:

有没有办法将属性选择器Expression&lt;Func&lt;T, TProperty&gt;&gt; 转换为Expression&lt;Func&lt;object, object&gt;&gt;,反之亦然?我已经知道如何转换为Expression&lt;Func&lt;T, object&gt;&gt; 使用...

Expression<Func<T, TProperty>> oldExp;
Expression.Lambda<Func<T, object>>(Expression.Convert(oldExp.Body, typeof(object)), oldExp.Parameters);

...但我需要有效地转换函数的参数和结果,而不仅仅是例如用 ExpressionVisitor 替换它们,因为它们需要稍后再转换回来。

【问题讨论】:

    标签: c# properties casting lambda expression


    【解决方案1】:

    您是正确的,您需要使用 ExpressionVisitor 和 ExpressionConvert。

    这是您要求的两种方法(以及一些支持方法):

    public Expression<Func<object, object>> ConvertToObject<TParm, TReturn>(Expression<Func<TParm, TReturn>> input)
    {
        var parm = Expression.Parameter(typeof(object));
        var castParm = Expression.Convert(parm, typeof(TParm));
        var body = ReplaceExpression(input.Body, input.Parameters[0], castParm);
        body = Expression.Convert(body, typeof(object));
        return Expression.Lambda<Func<object, object>>(body, parm);
    }
    
    public Expression<Func<TParm, TReturn>> ConvertBack<TParm, TReturn>(Expression<Func<object, object>> input)
    {
        var parm = Expression.Parameter(typeof(TParm));
        var castParm = Expression.Convert(parm, typeof(object));
        var body = ReplaceExpression(input.Body, input.Parameters[0], castParm);
        body = Expression.Convert(body, typeof(TReturn));
        return Expression.Lambda<Func<TParm, TReturn>>(body, parm);
    }
    
    Expression ReplaceExpression(Expression body, Expression source, Expression dest)
    {
        var replacer = new ExpressionReplacer(source, dest);
        return replacer.Visit(body);
    }
    
    public class ExpressionReplacer : ExpressionVisitor
    {
        Expression _source;
        Expression _dest;
    
        public ExpressionReplacer(Expression source, Expression dest)
        {
            _source = source;
            _dest = dest;
        }
    
        public override Expression Visit(Expression node)
        {
            if (node == _source)
                return _dest;
    
            return base.Visit(node);
        }
    }
    

    示例用法:

    Expression<Func<Customer, string>> expression = c => c.Name;
    var convertedExpression = ConvertToObject<Customer, string>(expression);
    var backExpression = ConvertBack<Customer, string>(convertedExpression);
    

    当然我们可以用一种类型参数更多的方法来代替原来的两种方法:

    public Expression<Func<TTargetParm, TTargetReturn>> ConvertGeneric<TParm, TReturn, TTargetParm, TTargetReturn>(Expression<Func<TParm, TReturn>> input)
    {
        var parm = Expression.Parameter(typeof(TTargetParm));
        var castParm = Expression.Convert(parm, typeof(TParm));
        var body = ReplaceExpression(input.Body, input.Parameters[0], castParm);
        body = Expression.Convert(body, typeof(TTargetReturn));
        return Expression.Lambda<Func<TTargetParm, TTargetReturn>>(body, parm);
    }
    

    示例用法:

    Expression<Func<Customer, string>> expression = c => c.Name;
    var convertedExpression = ConvertGeneric<Customer, string, object, object>(expression);
    var backExpression = ConvertGeneric<object, object, Customer, string>(convertedExpression);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多