Как я могу загрузить все объекты конфигурации объектов Entity Framework 4.1 через отражение? - PullRequest
4 голосов
/ 21 сентября 2011

В моем методе OnModelCreating для моего контекста данных я в настоящее время вручную отображаю все классы отображения конфигурации моих сущностей вручную, например:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new UserMap());
    // 20 or so mapping configuration below
}

Я хочу упростить это с помощью отражения, поэтому у меня есть следующий код:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Find all EntityTypeConfiguration classes in the assembly
        foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
            foreach (Type t in asm.GetTypes())
                if (t.IsDerivedFromOpenGenericType(typeof(EntityTypeConfiguration<>)))
                    modelBuilder.Configurations.Add(Activator.CreateInstance(t));   
    }

IsDerivedFromOpenGenericType от этого вопроса и работает правильно.

Проблема в том, что это не компилируется, потому что Activator.CreateInstance(t) возвращает object, но построитель модели ожидает System.Data.Entity.ModelConfiguration.ComplexTypeConfiguration<TComplexType>.

Обычно при использовании класса Activator я просто приводил бы объект к тому, что, как я ожидаю, будет иметь тип t (или то, что я ожидаю от класса), но так как он использует обобщенные элементы, я не знаю, способа сделать это.

У кого-нибудь есть идеи?

Ответы [ 4 ]

7 голосов
/ 13 октября 2015

Я не уверен, почему эту информацию так сложно найти (по крайней мере, для меня), но есть гораздо более простой способ сделать это подробно здесь .

public class MyDbContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Configurations.AddFromAssembly(Assembly.GetAssembly(GetType())); //Current Assembly
    base.OnModelCreating(modelBuilder);
  }
}
5 голосов
/ 04 мая 2012

Я получил это от Роуэн Миллер из Microsoft :

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {

        var addMethod = typeof (ConfigurationRegistrar)
            .GetMethods()
            .Single(m =>
                    m.Name == "Add" &&
                    m.GetGenericArguments().Any(a => a.Name == "TEntityType"));

        var assemblies = AppDomain.CurrentDomain
            .GetAssemblies()
            .Where(a => a.GetName().Name != "EntityFramework");

        foreach (var assembly in assemblies)
        {
            var configTypes = assembly
                .GetTypes()
                .Where(t => t.BaseType != null &&
                            t.BaseType.IsGenericType &&
                            t.BaseType.GetGenericTypeDefinition() == typeof (EntityTypeConfiguration<>));

            foreach (var type in configTypes)
            {
                var entityType = type.BaseType.GetGenericArguments().Single();

                var entityConfig = assembly.CreateInstance(type.FullName);
                addMethod.MakeGenericMethod(entityType)
                    .Invoke(modelBuilder.Configurations, new[] {entityConfig});
            }
        }

        base.OnModelCreating(modelBuilder);
    }
2 голосов
/ 05 мая 2012

Я нашел гораздо лучший способ сделать это, используя композицию с MEF:

public class Album
{
    public int AlbumId { get; set; }
    public int GenreId { get; set; }
    public int ArtistId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public string AlbumArtUrl { get; set; }
    public Genre Genre { get; set; }
    public Artist Artist { get; set; }
}

using System.Data.Entity.ModelConfiguration.Configuration;

namespace MvcMusicStore.Models
{
   public interface IEntityConfiguration
   {
       void AddConfiguration(ConfigurationRegistrar registrar);
   }
}

using System.ComponentModel.Composition;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Configuration;

namespace MvcMusicStore.Models.TypeConfig
{
  [Export(typeof(IEntityConfiguration))]
  public class AlbumTypeConfiguration : EntityTypeConfiguration<Album>, IEntityConfiguration
  {
    public AlbumTypeConfiguration()
    {
        ToTable("Album");
    }

    public void AddConfiguration(ConfigurationRegistrar registrar)
    {
        registrar.Add(this);
    }
  }
}

using System.Collections.Generic;
using System.ComponentModel.Composition;

namespace MvcMusicStore.Models
{
  public class ContextConfiguration
  {
      [ImportMany(typeof(IEntityConfiguration))]
      public IEnumerable<IEntityConfiguration> Configurations { get; set; }
  }
}

 using System;
 using System.ComponentModel.Composition.Hosting;
 using System.Data.Entity;
 using System.Data.Entity.ModelConfiguration;
 using System.Data.Entity.ModelConfiguration.Configuration;
 using System.Linq;
 using System.Reflection;

 namespace MvcMusicStore.Models
 {
   public class MusicStoreEntities : DbContext
   {
    public DbSet<Album> Albums { get; set; }
    public DbSet<Genre> Genres { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        var exports = container.GetExportedValues<IEntityConfiguration>();

        foreach (var entityConfiguration in exports)
        {
            entityConfiguration.AddConfiguration(modelBuilder.Configurations);
        }    
        base.OnModelCreating(modelBuilder);
    }
  }
}

credit: OdeToCode.com Composing Entity Framework Свободные конфигурации

1 голос
/ 21 сентября 2011

Здесь вы также должны использовать отражение.

Получите метод с помощью Type.GetMethod(), а затем создайте необходимую вам универсальную версию с помощью MethodInfo.MakeGenericMethod():

Type tCmpxTypeConfig = typeof (EntityTypeConfiguration<>);
tCmpxTypeConfig = tCmpxTypeConfig.MakeGenericType(t);

modelBuilder.Configurations.GetType()
    .GetMethod("Add", new Type[] { tCmpxTypeConfig })
    .MakeGenericMethod(t)
    .Invoke(modelBuilder.Configurations, 
        new object[] { Activator.CreateInstance(t) });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...