很抱歉没有找到更好的标题。我正在尝试通过 MEF 模块扩展 EF4 CTP5 模型:想法是指定一些基本实体。这些基本实体位于我的解决方案模型程序集中的 Context 类旁边。
例如,将有一个名为变量的实体。变量是一个非常通用的实体,我希望应用程序的某些模块指定特殊变量实体以提供更详细的属性,但它们应该存储在同一个表中(TPH - 每个层次结构的表)。
为此,我指定了一个接口 IModelContextExtension
public interface IModelContextExtension
{
void OnModelCreating(IModelBuilderFacade modelBuilder);
}
每个想要使用自定义变量的模块都必须导出一个实现此接口的类。在模型的 OnModelCreating 方法中,我循环每个注册的模块,并调用该模块的 OnModelCreating 方法。然后它可以在提供的IModelBuilderFacade 上调用例如“RegisterVariableType”,以宣布一个Variable-Derived-Type(例如MySpecialVariable2)。
** 有趣的部分:** RegisterVariableType 方法似乎工作得很好,除非 Variable-Derived-Type 位于另一个(MEF-Loaded)程序集中。如果我从另一个模块注册一个变量,那么整个映射似乎已损坏。因为,当我现在尝试向其存储库添加一个变量时,它在添加过程中崩溃:“序列不包含任何元素”。如果我从加载的模块中删除类型,它会像预期的那样工作。
如果有人感兴趣,我会发布 IRepository 的东西,但我敢肯定,那不是问题..
这里是来自我的上下文(从 DbContext 派生)类的 OnModelCreating 方法:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var modelBuilderFacade = new ModelBuilderFacade(modelBuilder);
modelBuilder.Entity<Variable>().HasKey(x => new { x.Id });
////////////////////////////////////
// register derived VariableTypes
modelBuilderFacade.RegisterVariableType(typeof(MySpecialCyclicVariable));
modelBuilderFacade.RegisterVariableType(typeof(MyVerySpecialVariable));
//modelBuilder.Entity<Variable>().HasKey(x => new { x.Id }); modelBuilder.Entity<Variable>()
// .Map<MySpecialVariabe>(m => m.Requires(DiscriminatorColumn).HasValue(typeof(MySpecialVariabe).Name))
// .Map<MyVerySpecialVariable>(m => m.Requires(DiscriminatorColumn).HasValue(typeof(MyVerySpecialVariable).Name))
// .ToTable(VariableTable);
if (ModelExtensions != null)
{
foreach (var modelContextExtension in ModelExtensions)
{
modelContextExtension.OnModelCreating(modelBuilderFacade);
}
}
Map<Variable>(modelBuilder, modelBuilderFacade.VariableTypes, VariableTable);
////////////////////////////////////
}
RegisterVariableType 函数将(变量派生的)类型添加到存储在 modelBuilderFacade 中的 IEnumerable。
添加类型后,我调用自己的 Map 函数来进行 TPH 映射。
[Export(typeof(IModelContextExtension))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class Context : IModelContextExtension
{
public void OnModelCreating(IModelBuilderFacade modelBuilder)
{
modelBuilder.RegisterVariableType(typeof(MyVerySpecialVariable2));
}
}
这里的地图功能:
private static void Map<T>(ModelBuilder modelBuilder, IEnumerable<Type> types, string table) where T : class
{
var entityTypeConfigurarion = modelBuilder.Entity<T>();
foreach (var variableType in types)
{
if (!typeof(T).IsAssignableFrom(variableType))
{
throw new InvalidOperationException(string.Format("Cannot map type '{0}' to type {1}", variableType, typeof(T)));
}
// #1: Get the generic Map method of the EntityTypeConfiguration<T>
MethodInfo genericMapMethod = GetGenericEntityTypeConfigurationMapMethod<T>(variableType);
// #2: Get generic type of RequiredMappingActionFactory
var requiredMappingFactoryType = typeof(RequiredMappingActionFactory<>).MakeGenericType(variableType);
// #3 get the action from generic mapping factory
var action = requiredMappingFactoryType.GetProperty("RequiredMappingAction").GetValue(null, null);
entityTypeConfigurarion =
genericMapMethod.Invoke(
entityTypeConfigurarion,
BindingFlags.Public | BindingFlags.Instance,
null,
new [] { /* and the */ action /* goes here */ },
null) as EntityTypeConfiguration<T>;
}
if (entityTypeConfigurarion == null)
{
throw new CompositionException("Something went terrible wrong!");
}
entityTypeConfigurarion.ToTable(table);
}
private static MethodInfo GetGenericEntityTypeConfigurationMapMethod<T>(Type variableType) where T : class
{
var mapMethod =
typeof(EntityTypeConfiguration<T>).GetMethods().Where(
mi => mi.Name == "Map" && mi.IsGenericMethodDefinition).FirstOrDefault();
return mapMethod.MakeGenericMethod(variableType);
}
这里是RequiredMappingActionFactory
internal static class RequiredMappingActionFactory<T> where T : class
{
public static string DiscriminatorColumn = "Discriminator";
public static Action<EntityMappingConfiguration<T>> RequiredMappingAction { get { return RequiredAction; } }
public static void RequiredAction(EntityMappingConfiguration<T> configuration)
{
configuration.Requires(DiscriminatorColumn).HasValue(typeof(T).Name);
}
}
希望有人可以帮助我,最好的问候,
切里奥,克里斯