繁体   English   中英

如何投射表达<Func<T1,bool> &gt; 表达<Func<T2,bool> &gt;?

[英]How cast Expression<Func<T1,bool>> to Expression<Func<T2,bool>>?

如何将Expression<Func<T1,bool>>Expression<Func<T2,bool>> 请注意,T1 和 T2 具有相同的接口。

这是一个示例解决方案,不要在真正的代码中使用它

如果childExpression使用除Base属性以外的其他内容,这将中断。 如果您有很多参数,这将中断(演示访问者以尽可能简单的方式实现)。 这在很多情况下可能会中断,它应该仅用于解释目的。

现在,解释

可以通过访问表达式并将参数替换为新参数来完成此任务:

class Base
{
    public string Name { get; set; }
}

class Child : Base { }

假设您有一个仅使用.Name Child Expression

var childExpression = (Expression<Func<Child, bool>>)(e => e.Name == "works!");

我们可以为Base类型而不是Child创建一个新参数:

var newParameter = Expression.Parameter(typeof(Base));

提取旧体:

var newBody = childExpression.Body;

好吧,这有一个问题:旧的主体使用了对旧参数的引用,我们需要将其替换为新的。

class ParameterReplacer : ExpressionVisitor
{
    private ParameterExpression _newParameter;

    public ParameterReplacer(ParameterExpression newParameter)
    {
        _newParameter = newParameter;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return _newParameter; // forget about the old one, return the new
    }
}

那么我们就可以通过适当的引用来获取我们的身体:

var body = new ParameterReplacer(newParameter).Visit(childExpression.Body);

并将结果组合在一个完美类型的Expression<Func<Base, bool>>

var expressionForBase = Expression.Lambda<Func<Base, bool>>(body, newParameter);

而且,当然,它有效:

var predicate = expressionForBase.Compile().Invoke(new Base
{
    Name = "works!"
}); // true!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM