Reflection to build list of EntityTypeConfiguration for Entity Framework CPT5
Asked Answered
V

3

6

I don't want to have to add each mapping class manually to the ModelBuilder() so was trying to use my limited knowledge of reflection to register them. This is what I have, and this is the error I am getting:

CODE:

private static ModelBuilder CreateBuilder() {
            var contextBuilder = new ModelBuilder();
            IEnumerable<Type> configurationTypes = typeof(DatabaseFactory)
                .Assembly
                .GetTypes()
                .Where(type => type.IsPublic && type.IsClass && !type.IsAbstract && !type.IsGenericType && typeof(EntityTypeConfiguration).IsAssignableFrom(type) && (type.GetConstructor(Type.EmptyTypes) != null));

            foreach (var configuration in configurationTypes.Select(type => (EntityTypeConfiguration)Activator.CreateInstance(type)))
            {
                contextBuilder.Configurations.Add(configuration);
            }

            return contextBuilder;
        }

ERROR: Error 2 The type arguments for method 'System.Data.Entity.ModelConfiguration.Configuration.ConfigurationRegistrar.Add(System.Data.Entity.ModelConfiguration.EntityTypeConfiguration)' cannot be inferred from the usage. Try specifying the type arguments explicitly. C:\root\development\playground\PostHopeProject\PostHope.Infrastructure.DataAccess\DatabaseFactory.cs 67 17 PostHope.Infrastructure.DataAccess

Volvulus answered 8/12, 2010 at 0:12 Comment(0)
G
13

Original answer:

http://areaofinterest.wordpress.com/2010/12/08/dynamically-load-entity-configurations-in-ef-codefirst-ctp5/

The details of the implied solution:

The above referenced article shows that you can use the dynamic keyword to bypass compile time type checking and thus get around the restriction of attempting to add the configuration to the generic Add() method of the DbModelBuilder. Here's a quick sample:

// Load all EntityTypeConfiguration<T> from current assembly and add to configurations
var mapTypes = from t in typeof(LngDbContext).Assembly.GetTypes()
               where t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)
               select t;

foreach (var mapType in mapTypes)
{
    // note: "dynamic" is a nifty piece of work which bypasses compile time type checking... (urgh??)
    //       Check out: http://msdn.microsoft.com/en-us/library/vstudio/dd264741%28v=vs.100%29.aspx
    dynamic mapInstance = Activator.CreateInstance(mapType);
    modelBuilder.Configurations.Add(mapInstance);
}

You can read more on using this keyword on MSDN

Gnosis answered 8/12, 2010 at 20:22 Comment(0)
M
1

Your var configuration is of type Type, which is not of type EntityTypeConfiguration. You'll have to provide the Add method an instance of EntityTypeConfiguration, presumably based upon your current type: configuration.

Moureaux answered 8/12, 2010 at 0:26 Comment(0)
T
0

You can also use this extension method

public static void RegisterEntityTypeConfiguration(this ModelBuilder modelBuilder, params Assembly[] assemblies)
    {
        var applyGenericMethod = typeof(ModelBuilder).GetMethods()
            .First(m => m.Name == nameof(ModelBuilder.ApplyConfiguration));

        var types = assemblies.SelectMany(a => a.GetExportedTypes())
            .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic);

        foreach (var type in types)
        {
            foreach (var @interface in type.GetInterfaces())
            {
                if ([email protected] ||
                    @interface.GetGenericTypeDefinition() != typeof(IEntityTypeConfiguration<>)) continue;
                var applyConcreteMethod =
                    applyGenericMethod.MakeGenericMethod(@interface.GenericTypeArguments[0]);
                applyConcreteMethod.Invoke(modelBuilder, new[] {Activator.CreateInstance(type)});
            }
        }
    }
Turf answered 19/5, 2023 at 13:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.