I am using the following class to wrap some DocumentDB access which allows me to store multiple entities in the same collection:
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;
}
}
The usage of this class is encapsulated inside a repository class. I'm trying to build the API of the repository class such that the consumer doesn't need to know about the usage of TypedEntity<T>
and can instead treat it as a source for just <T>
. For example, the repository has a method with this signature:
public async Task<IQueryable<T>> WhereAsync(Func<T, bool> predicate)
In order to actually retrieve this data, the predicate needs to be combined/converted with one that interacts with TypedEntity<T>
. This is the pseudo code that I'm picturing in my head for what I'd ultimately like to achieve:
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
}
This actually builds but ultimately results in an Expression that uses .Invoke around the passed in predicate (which DocumentDb is unable to understand). Is there some way that I can combine the type part with the passed in Func to build up the Expression manually?
You'll want to take in an Expression<>
rather than just a Func<>
. Then, it should be fairly easy to apply it in a Where()
clause after you've performed a Select()
projection:
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
}