Я ненавижу это делать, но я потратил слишком много времени на это. Ниже приведена попытка преобразовать метод c # в MethodBuilder. Результатом должен быть метод переопределения для EntityFramework OnModelCreating с использованием EFCodeFirst.
Вот метод в c # (названия моделей сокращены для простоты)
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Entity<Form>().ToTable("Form<Name>");
modelBuilder.Entity<FormAg>().ToTable("FormAg<Name>");
}
Вот метод, который я сейчас использую:
private static MethodBuilder FormContextBuildMethodOnModelCreating(TypeBuilder type, string formId) {
System.Reflection.MethodAttributes methodAttributes = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Family | System.Reflection.MethodAttributes.Virtual | System.Reflection.MethodAttributes.HideBySig;
//method
MethodBuilder OnModelCreating = type.DefineMethod("OnModelCreating", methodAttributes);
//method calls
MethodInfo Conventions = typeof(ModelBuilder).GetMethod("get_Conventions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
MethodInfo RemoveConventions = typeof(ConventionsConfiguration).GetMethod("Remove", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
MethodInfo Entity = typeof(ModelBuilder).GetMethod("Entity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
MethodInfo ToTable1 = typeof(System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<>).MakeGenericType(typeof(Form)).GetMethod("ToTable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(String) }, null);
MethodInfo ToTable2 = typeof(System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<>).MakeGenericType(typeof(FormAg)).GetMethod("ToTable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(String) }, null);
OnModelCreating.SetReturnType(typeof(void));
OnModelCreating.SetParameters(typeof(ModelBuilder));
ParameterBuilder modelBuilder = OnModelCreating.DefineParameter(1, ParameterAttributes.None, "modelBuilder");
ILGenerator Il = OnModelCreating.GetILGenerator();
Il.Emit(OpCodes.Nop);
Il.Emit(OpCodes.Ldarg_1);
Il.Emit(OpCodes.Callvirt, Conventions);
Il.Emit(OpCodes.Callvirt, RemoveConventions);
Il.Emit(OpCodes.Nop);
Il.Emit(OpCodes.Ldarg_1);
Il.Emit(OpCodes.Callvirt, Entity);
Il.Emit(OpCodes.Ldstr, "Form" + formId);
Il.Emit(OpCodes.Callvirt, ToTable1);
Il.Emit(OpCodes.Nop);
Il.Emit(OpCodes.Ldarg_1);
Il.Emit(OpCodes.Callvirt, Entity);
Il.Emit(OpCodes.Ldstr, "FormAg" + formId);
Il.Emit(OpCodes.Callvirt, ToTable2);
Il.Emit(OpCodes.Nop);
Il.Emit(OpCodes.Ret);
return OnModelCreating;
}
OpCodes были получены из рефлектора il вышеуказанного кода C #. По жизни я не могу понять, что здесь не так. Я сузил проблему до этого метода, так как все остальные свойства и что не построены правильно. Я могу вернуть пустое тело (Nop
+ Ret
), и оно отлично работает ...
Любая попытка использовать результирующий тип вызывает следующую ошибку:
An attempt was made to load a program with an incorrect format.
Любая помощь будет принята с благодарностью.