Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 替换表达式树中的类型_C#_Linq_Lambda_Expression - Fatal编程技术网

C# 替换表达式树中的类型

C# 替换表达式树中的类型,c#,linq,lambda,expression,C#,Linq,Lambda,Expression,我正在努力修改表达式树。我简化了示例,使其更易于在此处显示。让我们从两个类开始: public class Filter { public string FilterableProperty1 { get; set; } public string FilterableProperty2 { get; set; } } public class Entity { public string Filterab

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

    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类通过如下方法返回所需的实体:

    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);
        }
    }
    public IEnumerable<Entity> GetFilteredEntities()
    {
        return GetEntities(x => x.FilterableProperty1 == "Test");
    }
public IEnumerable GetEntities(表达式过滤器)
{
表达式convertedFilter=Expression.Lambda(
过滤体,
Expression.Parameter(typeof(Entity),filter.Parameters[0].Name));
使用(MyEntities entities=new MyEntities())
{
返回实体.entities.Where(convertedFilter);
}
}
所以基本上我只是改变表达式参数的类型。现在,当我像这样调用函数时:

    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);
        }
    }
    public IEnumerable<Entity> GetFilteredEntities()
    {
        return GetEntities(x => x.FilterableProperty1 == "Test");
    }
public IEnumerable GetFilteredEntities()
{
返回GetEntities(x=>x.FilterableProperty1==“Test”);
}

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

经过进一步搜索,我在此处找到了答案:。当我提交问题时,它没有出现在建议中

由于我并不真正需要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);
    }
}
//示例用法:返回entities.entities.Where(ExpressionTransformer.Transform(filter));
内部静态类表达式转换器,其中TTo:TFrom
{
公共类访问者:ExpressionVisitor
{
私有参数expression\u参数;
公共访问者(ParameterExpression参数)
{
_参数=参数;
}
受保护的重写表达式VisitParameter(ParameterExpression节点)
{
返回_参数;
}
}
公共静态表达式转换(表达式)
{
ParameterExpression参数=Expression.parameter(typeof(TTo));
Expression body=新访问者(参数).Visit(Expression.body);
返回表达式.Lambda(主体,参数);
}
}

如果你需要做一些类似的事情,但你不能使用接口,或者你不能让你的类实现该接口:答案也在上面提到的答案中

只是一句警告的话,因为我知道这很旧,可能没有被监控,但我偶然发现了它。如果您的对象未设置为本质相同,则还需要在Visitor类和泛型T上使用“VisitMember”的重写。在您的示例中,TTo和TFrom的泛型是等效的。您可以对具有与“VisitMember”类似属性的非等效对象执行此操作。