首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Expression<Func<FromType>>转换为Expression<Func<ToType>>

将Expression<Func<FromType>>转换为Expression<Func<ToType>>
EN

Stack Overflow用户
提问于 2011-08-13 22:24:25
回答 2查看 1.4K关注 0票数 2

如何创建泛型帮助器方法,以便在表达式中将Func使用的类型从一种类型转换为另一种类型

我有一个Expression<Func<IEmployee, bool>>,我想把它转换成

代码语言:javascript
复制
Expression<Func<Employee, bool>>.

第二个类型始终实现第一个类型。一个通用的解决方案就是我想要实现的。

编辑

为了更清楚,我对问题进行了编辑。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-14 00:25:39

那么,您可以创建一个表达式,该表达式进行强制转换,然后将其参数转发给原始表达式:

代码语言:javascript
复制
Expression<Func<IEmployee, bool>> source = ...

var param = Expression.Parameter(typeof(Employee));

// Types the argument as the type expected by the source expression
// and then forwards it...
var invocationExpr = Expression.Invoke
                     (source, Expression.TypeAs(param, typeof(IEmployee))); 

var result = Expression.Lambda<Func<Employee, bool>>(invocationExpr, param);

如果提供程序不支持调用表达式,那么您可能需要一个更复杂的解决方案来替换源表达式中的参数。

编辑:好的,既然你说你的提供者不喜欢结果表达式,这里有一个可供选择的例子。这是参数替换器应该是什么样子的一个非常粗略的剪裁(我现在只是把它写成一个样本),但它应该可以很好地满足您的目的。

代码语言:javascript
复制
public static class ParameterReplacer
{
    // Produces an expression identical to 'expression'
    // except with 'source' parameter replaced with 'target' parameter.     
    public static Expression<TOutput> Replace<TInput, TOutput>
                 (Expression<TInput> expression,
                  ParameterExpression source,
                  ParameterExpression target)
    {
        return new ParameterReplacerVisitor<TOutput>(source, target)
                  .VisitAndConvert(expression);
    }

    private class ParameterReplacerVisitor<TOutput> : ExpressionVisitor
    {
        private ParameterExpression _source;
        private ParameterExpression _target;

        public ParameterReplacerVisitor
              (ParameterExpression source, ParameterExpression target)
        {
            _source = source;
            _target = target;
        }

        internal Expression<TOutput> VisitAndConvert<T>(Expression<T> root)
        {
            return (Expression<TOutput>)VisitLambda(root);
        }

        protected override Expression VisitLambda<T>(Expression<T> node)
        {
            // Leave all parameters alone except the one we want to replace.
            var parameters = node.Parameters.Select
                             (p => p == _source ? _target : p);

            return Expression.Lambda<TOutput>(Visit(node.Body), parameters);
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            // Replace the source with the target, visit other params as usual.
            return node == _source ? _target : base.VisitParameter(node);
        }
    }
}

然后将其用作:

代码语言:javascript
复制
Expression<Func<IEmployee, bool>> expression = ...

var result = ParameterReplacer.Replace
                <Func<IEmployee, bool>, Func<Employee, bool>>
                (expression,
                 expression.Parameters.Single(), 
                 Expression.Parameter(typeof(Employee));
票数 6
EN

Stack Overflow用户

发布于 2011-08-13 22:41:45

如果第二个类型始终继承或实现第一个类型,则可以使用

代码语言:javascript
复制
Func<TOut, bool> Convert<TIn, TOut>(Func<TIn, bool> f) where TOut : TIn
{
    return (TOut x) => f((TIn)x);
}

如果没有这样的关系,就不能使用泛型。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7051003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档