i 担心找不到更好的标题。 我正试图通过MEF扩大EF4CTP5模式。 模块: 理想是调和一些基本实体。 这些基本实体位于我的背景类别旁,位于我的解决方案模拟大会。
例如,将有一个称为可变的实体。 可变性是一个非常一般的实体,需要一些应用模块来说明特别可变实体的巫术提供更为详细的特性,但应将其储存在同一表格中(TPH——每座等级表)。
To do so, i specified an interface IModelContextExtension
public interface IModelContextExtension
{
void OnModelCreating(IModelBuilderFacade modelBuilder);
}
想要使用习俗变量的每个模块都必须出口一个能够实施这一接口的类别。 在模型的“模拟”方法中,即每个已登记的模块,并使用该模块的“模拟方法”。 然后,它可以在IModelBuilderFacade提供的“RegisterVariableType”上宣布一个Variable-Derived-Type(例如MySpecialVariable2)。
** The interesting part: ** The RegisterVariableType method seems to work very good, except if the Variable-Derived-Type is located in another (MEF-Loaded) assembly. If i register a Variable from another module, than the complete mapping seems to be damaged. Because, when i now try to add a Variable to its Repository, it crashs during the add saying: "Sequence contains no elements". If i remove the type from the loaded module, it works like expected.
如果有人感兴趣,但我肯定会说,这不是问题,那么我就会把保存人放在一边。
这里,从我的背景(从DbContext)类中得出ModelCreating方法:
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);
////////////////////////////////////
}
The RegisterVariableType function adds the (Variable derived) types to an IEnumerable stored in the modelBuilderFacade.
在添加了这些类型之后,即我自己的地图功能,以图绘制地图。
[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);
}
以及此处要求采取的行动
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);
}
}
hopefully someone can help me, best regards,
cherio, Chris