使用表达式组合具有不同签名的函数

Using Expressions to combine Funcs with different signature

我正在使用以下 class 来包装一些 DocumentDB 访问,这允许我在同一个集合中存储多个实体:

public class TypedEntity<T> {
    public string Type { get; set; }

    public T Item { get; set; }

    public TypedEntity(T item) {
        Id = Guid.NewGuid().ToString();
        Item = item;
        Item.Id = Id;
        Type = typeof (T).FullName;
    } 
}

此 class 的用法封装在存储库 class 中。我正在尝试构建存储库 class 的 API,这样消费者就不需要知道 TypedEntity<T> 的用法,而是可以将其视为仅 <T>。例如,存储库有一个带有此签名的方法:

public async Task<IQueryable<T>> WhereAsync(Func<T, bool> predicate)

为了实际检索此数据,谓词需要 combined/converted 与 TypedEntity<T> 交互。这是我在脑海中为我最终想要实现的目标描绘的伪代码:

public async Task<IQueryable<T>> WhereAsync(Func<T, bool> predicate) {
    // remembering that dataSource is talking to a backing store of TypedEntity<T>
    var queryable = dataSource.Where(x => x.Type == typeof(T).FullName && predicate(x.Item));
   // ... other business logic stuff
}

这实际上构建但最终导致表达式使用 .Invoke 围绕传入的谓词(DocumentDb 无法理解)。有什么方法可以将类型部分与传入的 Func 结合起来手动构建表达式吗?

你会想要 Expression<> 而不仅仅是 Func<>。然后,在执行 Select() 投影后,将它应用到 Where() 子句中应该相当容易:

public async Task<IQueryable<T>> WhereAsync(Expression<Func<T, bool>> predicate) {
    // remembering that dataSource is talking to a backing store of TypedEntity<T>
    var typeName = typeof(T).FullName;
    var queryable = dataSource.Where(x => x.Type == typeName)
        .Select(x => x.Item)
        .Where(predicate);
   // ... other business logic stuff
}