lundi 3 août 2020

Invoke generic method at runtime with reflection

I'm trying to create a convention style class for Entity Framework Core 3 and a little stumped on a generics scenario. I'm not using DbSet<TEntity> SomeEntities { get; set; }, rather I've created a core EntityDbContext which provides CQRS interfaces and access to the DbSets is done with dbContext.Set<TEntity>(). This means I have a reusable DbContext across all projects I use this framework with which is great, but it does mean I have to think differently from time to time.

So I have a requirement to provide Temporal Table support and I annotate my entity classes with an empty interface called IHistoryEnabled. In My DbModelCreator class I scan loaded assemblies for classes implementing IEfDbConvention and then call SetConvention(...). In the HistoryEnabledTableConvention I just need to check if the entity implements IHistoryEnabled and then call:

modelBuilder.Entity<TEntity>(b => b.UseTemporalTable());

That is provided by the library EntityFrameworkCore.TemporalTables. Because this convention has no idea aboout the type I can't specify it directly as a generic type. Does anyone know how I can actually invoke the Entity method shown but using a type determined at runtime? As an example I have an entity class Employment : IHistoryEnabled and the ClrType at runtime is Employment enter image description here

Here's the code as text for convenience:

public class HistoryEnabledTableConvention : IEfDbConvention
{
    public void SetConvention(ModelBuilder modelBuilder)
    {
        foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
        {
            if (entityType.ClrType.GetInterfaces().ToList().Any(t => t.Name == nameof(IHistoryEnabled)))
            {
                // Need to replace this line...
                modelBuilder.Entity<TEntity>(b => b.UseTemporalTable());
            }

        }

    }
}

The full solution with a working example is here. To get it running just test the ExampleConsoleApp as the start project.





Aucun commentaire:

Enregistrer un commentaire