Introduction
In entity framework, we've been able to load all "EntityTypeConfiguration
" classes using the below method:
modelBuilder.Configurations.AddFromAssembly(assembly)
In EF-Core, this is not available anymore, but we have to add each configuration separately using a generic method that takes the type of the entity as type argument.
modelBuilder.ApplyConfiguration<EntityType>(<code>config</code>)
To add all configurations from specific assembly, we can create an extension method to do the same job as below:
public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
}
The first thing we'll do is to fetch all configurations that implements the IEntityTypeConfiguration<>
interface, knowing that the configuration is a non-abstract non-nested class:
var configurations = assembly.DefinedTypes.Where(t =>
t.ImplementedInterfaces.Any(i =>
i.IsGenericType &&
i.Name.Equals(typeof(IEntityTypeConfiguration<>).Name,
StringComparison.InvariantCultureIgnoreCase)
)&&
t.IsClass &&
!t.IsAbstract &&
!t.IsNested)
.ToList();
Then we'll use reflection to invoke the ApplyConfiguration
method of the model builder instance for each configuration we have:
foreach (var configuration in configurations)
{
var entityType = configuration.BaseType.GenericTypeArguments.SingleOrDefault(t => t.IsClass);
var applyConfigMethods = typeof(ModelBuilder).GetMethods().Where(m => m.Name.Equals("ApplyConfiguration") && m.IsGenericMethod);
var applyConfigMethod = applyConfigMethods.Single(m => m.GetParameters().Any(p => p.ParameterType.Name.Equals(typeof(IEntityTypeConfiguration<>).Name)));
var applyConfigGenericMethod = applyConfigMethod.MakeGenericMethod(entityType);
applyConfigGenericMethod.Invoke(modelBuilder,
new object[] { Activator.CreateInstance(configuration) });
}
The final code will look like below:
public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
var configurations = assembly.DefinedTypes.Where(t =>
t.ImplementedInterfaces.Any(i =>
i.IsGenericType &&
i.Name.Equals(typeof(IEntityTypeConfiguration<>).Name,
StringComparison.InvariantCultureIgnoreCase)
)&&
t.IsClass &&
!t.IsAbstract &&
!t.IsNested)
.ToList();
foreach (var configuration in configurations)
{
var entityType = configuration.BaseType.GenericTypeArguments.SingleOrDefault(t => t.IsClass);
var applyConfigMethod = typeof(ModelBuilder).GetMethod("ApplyConfiguration");
var applyConfigGenericMethod = applyConfigMethod.MakeGenericMethod(entityType);
applyConfigGenericMethod.Invoke(modelBuilder,
new object[] { Activator.CreateInstance(configuration) });
}
}
Usage
In this example, we'll assume that the configurations exist in the same assembly of the DbContext
, so our code will be like:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}