.net 转换表达式<;Func<;FromType>&燃气轮机;表达<;Func<;ToType>&燃气轮机;

.net 转换表达式<;Func<;FromType>&燃气轮机;表达<;Func<;ToType>&燃气轮机;,.net,linq,expression-trees,.net,Linq,Expression Trees,如何创建泛型帮助器方法来将Func使用的类型从表达式中的一种类型转换为另一种类型 我有一个表达式,我想把它转换成 Expression<Func<Employee, bool>>. 表达式。 第二种类型始终实现第一种类型。一个通用的解决方案就是我想要实现的 编辑 我对问题进行了编辑,以便更清楚。如果第二种类型始终继承或实现第一种类型,则可以使用 Func<TOut, bool> Convert<TIn, TOut>(Func<TIn, b

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

我有一个
表达式
,我想把它转换成

Expression<Func<Employee, bool>>.
表达式。
第二种类型始终实现第一种类型。一个通用的解决方案就是我想要实现的

编辑


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

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

Func<TOut, bool> Convert<TIn, TOut>(Func<TIn, bool> f) where TOut : TIn
{
    return (TOut x) => f((TIn)x);
}
Func Convert(Func f)其中TOut:TIn
{
返回(TOut x)=>f((TIn)x);
}

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

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

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);
表达式源=。。。
var param=表达式参数(typeof(Employee));
//将参数键入为源表达式所需的类型
//然后转发它。。。
var invocationExpr=Expression.Invoke
(source,Expression.TypeAs(param,typeof(IEEmployee));
var result=Expression.Lambda(invocationExpr,param);
如果提供程序不支持调用表达式,则可能需要更多 替换源表达式中的参数的复杂解决方案

编辑:好的,既然你说你的提供者不喜欢结果表达式,这里有一个替代的例子。这是一个真正粗略的参数替换程序(我现在只是写了一个示例),但它应该可以很好地满足您的需要

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);
        }
    }
}
公共静态类参数替换器
{
//生成与“表达式”相同的表达式
//“源”参数替换为“目标”参数时除外。
公共静态表达式替换
(表情,
参数表达式源,
参数表达式(目标)
{
返回新参数REPLACEVISITOR(源、目标)
.VisitAndConvert(表达式);
}
私有类参数replacervisitor:ExpressionVisitor
{
私有参数表达式_源;
私有参数expression\u目标;
公共参数置换器
(ParameterExpression源,ParameterExpression目标)
{
_来源=来源;
_目标=目标;
}
内部表达式VisitAndConvert(表达式根)
{
返回(表达式)VisitLambda(根);
}
受保护的重写表达式VisitLambda(表达式节点)
{
//除了要替换的参数外,不要使用其他参数。
var参数=node.parameters.Select
(p=>p==\u来源?\u目标:p);
返回表达式.Lambda(访问(node.Body),参数);
}
受保护的重写表达式VisitParameter(ParameterExpression节点)
{
//将源替换为目标,照常访问其他参数。
返回节点==\u源?\u目标:base.VisitParameter(节点);
}
}
}
然后将其用作:

Expression<Func<IEmployee, bool>> expression = ...

var result = ParameterReplacer.Replace
                <Func<IEmployee, bool>, Func<Employee, bool>>
                (expression,
                 expression.Parameters.Single(), 
                 Expression.Parameter(typeof(Employee));
Expression=。。。
var结果=参数更换器。更换
(表情,
expression.Parameters.Single(),
表达式.参数(typeof(Employee));

对不起,我应该提到是的,第二种类型总是实现第一种类型。如果我在表达式中使用Func怎么办?如果你有
表达式
,那么你就没有
Func
,你应该在问题中这样说,因为这是一个完全不同的问题。很抱歉没有完全清楚在这一点上,问题标题确实提到了convert Expression Func,其内容不够清晰。我使用的是Teleriks OpenAccess,它似乎不喜欢生成的表达式。好的,等一下。我会给你一个参数替换的示例。不,得到一个空对象异常,只是现在查看它,然后发布ba在接下来的10分钟内确认。非常感谢您的帮助。Ani,参数替换器似乎正在正常工作,但无论出于何种原因,Teleriks OpenAccess抛出了一个“对象引用未设置为对象实例”异常。真正的痛苦我希望我正在做的工作能够正常工作,那就是将规范传递给存储库以供执行。祝您好运在。如果需要,请发布另一个问题。:)