簡體   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