.net 转换表达式<;Func<;FromType>&燃气轮机;表达<;Func<;ToType>&燃气轮机;
如何创建泛型帮助器方法来将Func使用的类型从表达式中的一种类型转换为另一种类型 我有一个.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
表达式
,我想把它转换成
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抛出了一个“对象引用未设置为对象实例”异常。真正的痛苦我希望我正在做的工作能够正常工作,那就是将规范传递给存储库以供执行。祝您好运在。如果需要,请发布另一个问题。:)