|
1 | 1 | using System; |
2 | 2 | using System.Collections.Generic; |
| 3 | +using System.Linq; |
3 | 4 | using System.Linq.Expressions; |
| 5 | +using System.Reflection; |
4 | 6 | using FreeSql; |
5 | 7 | using FreeSql.DataAnnotations; |
6 | 8 | using FreeSql.Extensions.EfCoreFluentApi; |
@@ -34,4 +36,103 @@ public static ICodeFirst Entity(this ICodeFirst codeFirst, Type entityType, Acti |
34 | 36 | codeFirst.ConfigEntity(entityType, tf => modelBuilder(new EfCoreTableFluent(cf._orm, tf, entityType))); |
35 | 37 | return codeFirst; |
36 | 38 | } |
| 39 | + |
| 40 | + public static ICodeFirst ApplyConfiguration<TEntity>(this ICodeFirst codeFirst, IEntityTypeConfiguration<TEntity> configuration) where TEntity : class |
| 41 | + { |
| 42 | + return codeFirst.Entity<TEntity>(eb => |
| 43 | + { |
| 44 | + configuration.Configure(eb); |
| 45 | + }); |
| 46 | + } |
| 47 | +#if net40 |
| 48 | +#else |
| 49 | + static IEnumerable<MethodInfo> GetExtensionMethods(this Assembly assembly, Type extendedType) |
| 50 | + { |
| 51 | + var query = from type in assembly.GetTypes() |
| 52 | + where !type.IsGenericType && !type.IsNested |
| 53 | + from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) |
| 54 | + where method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false) |
| 55 | + where method.GetParameters()[0].ParameterType == extendedType |
| 56 | + select method; |
| 57 | + return query; |
| 58 | + } |
| 59 | + |
| 60 | + /// <summary> |
| 61 | + /// 根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类 |
| 62 | + /// </summary> |
| 63 | + /// <param name="codeFirst"></param> |
| 64 | + /// <param name="assembly"></param> |
| 65 | + /// <param name="predicate"></param> |
| 66 | + /// <returns></returns> |
| 67 | + public static ICodeFirst ApplyConfigurationsFromAssembly(this ICodeFirst codeFirst, Assembly assembly, Func<Type, bool> predicate = null) |
| 68 | + { |
| 69 | + IEnumerable<TypeInfo> typeInfos = assembly.DefinedTypes.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition); |
| 70 | + |
| 71 | + MethodInfo methodInfo = typeof(FreeSqlDbContextExtensions).Assembly.GetExtensionMethods(typeof(ICodeFirst)) |
| 72 | + .Single((e) => e.Name == "Entity" && e.ContainsGenericParameters); |
| 73 | + |
| 74 | + if (methodInfo == null) return codeFirst; |
| 75 | + |
| 76 | + foreach (TypeInfo constructibleType in typeInfos) |
| 77 | + { |
| 78 | + if (constructibleType.GetConstructor(Type.EmptyTypes) == null || predicate != null && !predicate(constructibleType)) |
| 79 | + { |
| 80 | + continue; |
| 81 | + } |
| 82 | + |
| 83 | + foreach (var @interface in constructibleType.GetInterfaces()) |
| 84 | + { |
| 85 | + if (@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)) |
| 86 | + { |
| 87 | + var type = @interface.GetGenericArguments().First(); |
| 88 | + var efFluentType = typeof(EfCoreTableFluent<>).MakeGenericType(type); |
| 89 | + var actionType = typeof(Action<>).MakeGenericType(efFluentType); |
| 90 | + |
| 91 | + //1.需要实体和Configuration配置 |
| 92 | + //codeFirst.Entity<ToDoItem>(eb => |
| 93 | + //{ |
| 94 | + // new ToDoItemConfiguration().Configure(eb); |
| 95 | + //}); |
| 96 | + |
| 97 | + //2.需要实体 |
| 98 | + //Action<EfCoreTableFluent<ToDoItem>> x = new Action<EfCoreTableFluent<ToDoItem>>(e => |
| 99 | + //{ |
| 100 | + // object o = Activator.CreateInstance(constructibleType); |
| 101 | + // constructibleType.GetMethod("ApplyConfiguration")?.Invoke(o, new object[1] { e }); |
| 102 | + //}); |
| 103 | + //codeFirst.Entity<ToDoItem>(x); |
| 104 | + |
| 105 | + //3.实现动态调用泛型委托 |
| 106 | + DelegateBuilder delegateBuilder = new DelegateBuilder(constructibleType); |
| 107 | + MethodInfo applyconfigureMethod = delegateBuilder.GetType().GetMethod("ApplyConfiguration")?.MakeGenericMethod(type); |
| 108 | + if (applyconfigureMethod == null) continue; |
| 109 | + Delegate @delegate = Delegate.CreateDelegate(actionType, delegateBuilder, applyconfigureMethod); |
| 110 | + |
| 111 | + methodInfo.MakeGenericMethod(type).Invoke(null, new object[2] |
| 112 | + { |
| 113 | + codeFirst, |
| 114 | + @delegate |
| 115 | + }); |
| 116 | + |
| 117 | + } |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + return codeFirst; |
| 122 | + } |
| 123 | + class DelegateBuilder |
| 124 | + { |
| 125 | + private readonly Type type; |
| 126 | + |
| 127 | + public DelegateBuilder(Type type) |
| 128 | + { |
| 129 | + this.type = type; |
| 130 | + } |
| 131 | + public void ApplyConfiguration<T>(EfCoreTableFluent<T> ex) |
| 132 | + { |
| 133 | + object o = Activator.CreateInstance(type); |
| 134 | + type.GetMethod("Configure")?.Invoke(o, new object[1] { ex }); |
| 135 | + } |
| 136 | + } |
| 137 | +#endif |
37 | 138 | } |
0 commit comments