繁体   English   中英

替换表达式树中的类型

[英]Replace a type in an expression tree

我正在努力修改表达式树。 我简化了示例,使其更易于在此处显示。 让我们从两个类开始:

    public class Filter
    {
        public string FilterableProperty1 { get; set; }
        public string FilterableProperty2 { get; set; }
    }

    public class Entity
    {
        public string FilterableProperty1 { get; set; }
        public string FilterableProperty2 { get; set; }
        public string NonFilterableProperty { get; set; }
    }

Filter类中的所有属性也存在于Entity类中。 现在,我想使用Filter类通过以下方法返回所需的实体:

    public IEnumerable<Entity> GetEntities(Expression<Func<Filter, bool>> filter)
    {
        Expression<Func<Entity, bool>> convertedFilter = Expression.Lambda<Func<Entity, bool>>(
            filter.Body,
            Expression.Parameter(typeof(Entity), filter.Parameters[0].Name));

        using (MyEntities entities = new MyEntities())
        {
            return entities.Entities.Where(convertedFilter);
        }
    }

所以基本上,我只是更改expression参数的类型。 现在,当我这样调用函数时:

    public IEnumerable<Entity> GetFilteredEntities()
    {
        return GetEntities(x => x.FilterableProperty1 == "Test");
    }

我得到一个异常,说在指定的查询表达式中找不到参数x。 显然,通过替换ParameterExpression可以破坏一些东西。 如何创建具有正确类型的新表达式来接管(或重建)原始表达式的主体?

经过更多搜索后,我在这里找到了答案: 如何更改表达式树中的类型? 当我提交问题时,它没有出现在建议中。

因为我实际上并不需要Filter类,所以我只创建了一个我希望能够过滤的属性(IEntity)的接口,并修改了Entity类来实现它。 现在,我可以通过以下方式获得所需的结果:

// Example use: return entities.Entities.Where(ExpressionTransformer<IEntity,Entity>.Transform(filter));
internal static class ExpressionTransformer<TFrom, TTo> where TTo : TFrom
{
    public class Visitor : ExpressionVisitor
    {
        private ParameterExpression _parameter;

        public Visitor(ParameterExpression parameter)
        {
            _parameter = parameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return _parameter;
        }
    }

    public static Expression<Func<TTo, bool>> Tranform(Expression<Func<TFrom, bool>> expression)
    {
        ParameterExpression parameter = Expression.Parameter(typeof(TTo));
        Expression body = new Visitor(parameter).Visit(expression.Body);
        return Expression.Lambda<Func<TTo, bool>>(body, parameter);
    }
}

万一您需要做类似的事情但不能使用接口或无法使类实现该接口:答案也在上述答案中

暂无
暂无

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

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