In short, here's what I am trying to do: register a HasQueryFilter lambda expression for entities in a DbContext.OnModelCreating where I am enumerating an unknown set of entities that I DO know implement an interface.
The code (simplified for this example):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes()) {
Expression<Func<ITenantScoped, bool>> filter = e => contextAccessor.Get<ITenantContext>().CanAccessTenant(e.TenantId);
modelBuilder.Entity(entityType.ClrType).HasQueryFilter(filter);
}
}
Some key notes:
- ITenantScoped is an interface with one property TenantId.
- contextAccessor.Get invokes an AsyncLocal and so it needs to be in the lambda to be called whenever it is invoked.
- The intent of all this is to raise an exception if an entity with a TenantId I'm not allowed to access is found.
The problem: HasQueryFilter
vomits an exception because it expects the filter to be of type Expression<Func<MyEntityType, bool>>
(where MyEntityType is the actual type of the entity).
I know the type of the entity from the entityType.ClrType, BUT I'm at a loss as to how to convert this Lambda function to a type where the type is known at runtime and not compile time.
I'm fairly new to c#, so I might be missing something obvious (hoping so, actually).
Is there a way to do what I want here? I'm not married to the approach, but I do need to make sure that EF access to the entities is protected.