using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using FreeSql; using FreeSql.DataAnnotations; using FreeSql.Extensions.EfCoreFluentApi; using FreeSql.Internal.CommonProvider; partial class FreeSqlDbContextExtensions { /// /// EFCore 95% 相似的 FluentApi 扩展方法 /// /// /// /// /// public static ICodeFirst Entity(this ICodeFirst codeFirst, Action> modelBuilder) { var cf = codeFirst as CodeFirstProvider; codeFirst.ConfigEntity(tf => modelBuilder(new EfCoreTableFluent(cf._orm, tf))); return codeFirst; } /// /// EFCore 95% 相似的 FluentApi 扩展方法 /// /// /// 实体类型 /// /// public static ICodeFirst Entity(this ICodeFirst codeFirst, Type entityType, Action modelBuilder) { var cf = codeFirst as CodeFirstProvider; codeFirst.ConfigEntity(entityType, tf => modelBuilder(new EfCoreTableFluent(cf._orm, tf, entityType))); return codeFirst; } public static ICodeFirst ApplyConfiguration(this ICodeFirst codeFirst, IEntityTypeConfiguration configuration) where TEntity : class { return codeFirst.Entity(eb => { configuration.Configure(eb); }); } #if net40 #else static IEnumerable GetExtensionMethods(this Assembly assembly, Type extendedType) { var query = from type in assembly.GetTypes() where !type.IsGenericType && !type.IsNested from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false) where method.GetParameters()[0].ParameterType == extendedType select method; return query; } /// /// 根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类 /// /// /// /// /// public static ICodeFirst ApplyConfigurationsFromAssembly(this ICodeFirst codeFirst, Assembly assembly, Func predicate = null) { IEnumerable typeInfos = assembly.DefinedTypes.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition); MethodInfo methodInfo = typeof(FreeSqlDbContextExtensions).Assembly.GetExtensionMethods(typeof(ICodeFirst)) .Single((e) => e.Name == "Entity" && e.ContainsGenericParameters); if (methodInfo == null) return codeFirst; foreach (TypeInfo constructibleType in typeInfos) { if (constructibleType.GetConstructor(Type.EmptyTypes) == null || predicate != null && !predicate(constructibleType)) { continue; } foreach (var @interface in constructibleType.GetInterfaces()) { if (@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)) { var type = @interface.GetGenericArguments().First(); var efFluentType = typeof(EfCoreTableFluent<>).MakeGenericType(type); var actionType = typeof(Action<>).MakeGenericType(efFluentType); //1.需要实体和Configuration配置 //codeFirst.Entity(eb => //{ // new ToDoItemConfiguration().Configure(eb); //}); //2.需要实体 //Action> x = new Action>(e => //{ // object o = Activator.CreateInstance(constructibleType); // constructibleType.GetMethod("ApplyConfiguration")?.Invoke(o, new object[1] { e }); //}); //codeFirst.Entity(x); //3.实现动态调用泛型委托 DelegateBuilder delegateBuilder = new DelegateBuilder(constructibleType); MethodInfo applyconfigureMethod = delegateBuilder.GetType().GetMethod("ApplyConfiguration")?.MakeGenericMethod(type); if (applyconfigureMethod == null) continue; Delegate @delegate = Delegate.CreateDelegate(actionType, delegateBuilder, applyconfigureMethod); methodInfo.MakeGenericMethod(type).Invoke(null, new object[2] { codeFirst, @delegate }); } } } return codeFirst; } class DelegateBuilder { private readonly Type type; public DelegateBuilder(Type type) { this.type = type; } public void ApplyConfiguration(EfCoreTableFluent ex) { object o = Activator.CreateInstance(type); type.GetMethod("Configure")?.Invoke(o, new object[1] { ex }); } } #endif }