在我的数据上下文的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
来自this question且工作正常。
问题是这不能编译,因为Activator.CreateInstance(t)
返回object
,但模型构建器期望System.Data.Entity.ModelConfiguration.ComplexTypeConfiguration<TComplexType>
。
通常在使用Activator
类时,我会将对象强制转换为我期望的类型t
(或者我期望该类采用的),但由于这是使用泛型我不知道如何做到这一点。
有没有人有任何想法?
答案 0 :(得分:6)
我不确定为什么这些信息很难找到(至少对我而言),但有一个更简单的方法来详细地做here。
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.AddFromAssembly(Assembly.GetAssembly(GetType())); //Current Assembly
base.OnModelCreating(modelBuilder);
}
}
答案 1 :(得分:5)
我是从Rowan Miller at 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 :(得分:2)
我发现使用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);
}
}
}
信用:OdeToCode.com Composing Entity Framework Fluent Configurations
答案 3 :(得分:1)
你也必须在这里使用反射。
使用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) });