Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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_Linq Expressions - Fatal编程技术网

C# 修改包装类的谓词表达式

C# 修改包装类的谓词表达式,c#,linq,linq-expressions,C#,Linq,Linq Expressions,我有一个repository类,它允许使用lambda表达式(简化的部分代码)进行查询: 公共类存储库:IRepository { 公共IList查找(表达式筛选器) { 返回SomeQueryProvider.Where(filter.ToList(); } } 但是,对于特定的提供程序,我需要将原始对象包装到另一个类中: public class Wrapped<T> { public T OriginalObject { get; set; } } 公共类包

我有一个repository类,它允许使用lambda表达式(简化的部分代码)进行查询:

公共类存储库:IRepository
{
公共IList查找(表达式筛选器)
{
返回SomeQueryProvider.Where(filter.ToList();
}
}    
但是,对于特定的提供程序,我需要将原始对象包装到另一个类中:

public class Wrapped<T>
{
    public T OriginalObject { get; set; }
}
公共类包装
{
公共T原始对象{get;set;}
}
因此,在本例中,我还需要将传入谓词表达式包装到另一个表达式中:

public class AnotherRepository<T>: IRepository<T> 
{
    public IList<T> Find(Expression<Func<T, bool>> filter)
    {
        Expression<Func<Wrapped<T>, bool>> wrappedFilter = ...
        return AnotherQueryProvider.Where(wrappedFilter).ToList();
    }
}
public类另一个存储库:IRepository
{
公共IList查找(表达式筛选器)
{
表达式wrappedFilter=。。。
返回另一个queryProvider.Where(wrappedFilter.ToList();
}
}
例如,
x=>x.ParentId==123
应该变成
x=>x.OriginalObject.ParentId==123


我找不到这个场景的例子,我自己也很难解决这个问题。如何使用
OriginalObject
属性预先编写谓词表达式?

回答具体问题

表达

Expression<Func<Wrapped<T>, T>> e1 = w => w.OriginalObject;
Expression<Func<T, bool>> e2 = o => o.ParentId == 123;
现在讨论的方法可能是这样的:

partial class ExpressionUtils
{
    public static Expression<Func<Wrapped<T>, TResult>> ToWrapped<T, TResult>(this Expression<Func<T, TResult>> source)
    {
        Expression<Func<Wrapped<T>, T>> unwrap = w => w.OriginalObject;
        var parameter = unwrap.Parameters[0];
        var body = source.Body.ReplaceParameter(source.Parameters[0], unwrap.Body);
        return Expression.Lambda<Func<Wrapped<T>, TResult>>(body, parameter);
    }
}

选择
OriginalObject
然后按原样使用
过滤器如何:
另一个查询提供程序。选择(x=>x.OriginalObject).Where(filter.ToList()
事实上,如果您搜索,有很多示例,但正如其他评论员所提到的,您可以简单地交换
Where
Select
(您的示例应该有
Select
,以便编译)。@OfirWinegarten谢谢,出于某种原因,我没有想到最简单的解决方案。我会接受这个答案,因为它回答了这个问题,即使问题评论中给出的解决方案更适合这种情况。
Expression<Func<Wrapped<T>, T>> e3 = w => w.OriginalObject.ParentId == 123;
public static partial class ExpressionUtils
{ 
    public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
    {
        return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
    }
    class ParameterReplacer : ExpressionVisitor
    {
        public ParameterExpression Source;
        public Expression Target;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == Source ? Target : base.VisitParameter(node);
        }
    }
}
partial class ExpressionUtils
{
    public static Expression<Func<Wrapped<T>, TResult>> ToWrapped<T, TResult>(this Expression<Func<T, TResult>> source)
    {
        Expression<Func<Wrapped<T>, T>> unwrap = w => w.OriginalObject;
        var parameter = unwrap.Parameters[0];
        var body = source.Body.ReplaceParameter(source.Parameters[0], unwrap.Body);
        return Expression.Lambda<Func<Wrapped<T>, TResult>>(body, parameter);
    }
}
var wrappedFilter = filter.ToWrapped();