在C#表达式中使用查询对象返回其他类型

时间:2018-07-23 15:22:53

标签: c# linq generics lambda expression

出于参数的原因,我目前有一个数据对象,我称它为foo ...

public class Foo 
{
   public int IndexedKey { get; set;}
   public string NonIndexedData {get; set;}
}

我有一个通用存储库,我想使用该存储库查询该对象,但是由于对数据库的权限,我不允许进行全表扫描。因此,我要负责创建安全的查询对象。

public class FooQuery
{
    public int IndexedKey
}

通用存储库允许使用任意谓词,并且当前具有类似于以下内容的实现...

public class FooRepo : IGenericRepo<Foo>
{
    private ICollection<Foo> _allFooRecords; //Imagine this is populated

    public ICollection<Foo> GetWhere(Expression<Func<Foo, bool>> criteria)
    {
        return _allFooRecords.Where(criteria.Compile())
    }
}

我希望能够执行以下操作...

public class FooRepo : IGenericRepo<Foo, FooQuery>
{
    private ICollection<Foo> _allFooRecords; //Imagine this is populated

    public ICollection<Foo> GetWhere(Expression<Func<FooQuery, bool>> criteria)
    {
        return _allFooRecords.Where(criteria.Compile())
    }
}

以上内容无法编译。我知道FooQuery的属性肯定包含与Foo类的indexed属性匹配的正确字段,但是我不能再使用该标准。Compile因为它将返回与搜索Foo集合不兼容的函数。有没有一种方法可以使上述签名起作用,以及我需要对实现进行哪些更改才能使其正常工作。

非常感谢

1 个答案:

答案 0 :(得分:2)

您的要求是:自动将视图模型表达式Expression<Func<FooQuery, bool>>转换为实际模型表达式Expression<Func<Foo, bool>>FooQuery实际上是您的ViewModel,但是Foo是真实的Model

Automapper可以发挥作用。

//wrap the translate in base class, so you don't have to do it in each repo
public class BaseRepo<TEntity, TViewMode> : IGenericRepo<TEntity, TViewMode>
{
    ....
    public IWhatever<TEntity> Where(Expression<Func<TViewMode, bool>> vmExpression)
    {
        var expression = Mapper.Map<Expression<Func<TEntity, bool>>>(vmExpression);
        return whateverDataOrQuery.Where(expression);
    }

}

完整的官方文件在这里:

表达翻译:https://github.com/AutoMapper/AutoMapper/blob/master/docs/Expression-Translation-(UseAsDataSource).md